2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
15 #include <afsconfig.h>
16 #include "afs/param.h"
21 #include "afs/sysincludes.h" /* Standard vendor system headers */
22 #include "afsincludes.h" /* Afs-based standard headers */
23 #include "afs/afs_stats.h" /* statistics */
24 #include "afs/afs_cbqueue.h"
25 #include "afs/nfsclient.h"
26 #include "afs/afs_osidnlc.h"
27 #include "afs/unified_afs.h"
29 /* Static prototypes */
30 static int HandleGetLock(register struct vcache *avc,
31 register struct AFS_FLOCK *af,
32 register struct vrequest *areq, int clid);
33 static int GetFlockCount(struct vcache *avc, struct vrequest *areq);
34 static int lockIdcmp2(struct AFS_FLOCK *flock1, struct vcache *vp,
35 register struct SimpleLocks *alp, int onlymine,
37 static void DoLockWarning(void);
39 /* int clid; * non-zero on SGI, OSF, SunOS, Darwin, xBSD ** XXX ptr type */
41 lockIdSet(struct AFS_FLOCK *flock, struct SimpleLocks *slp, int clid)
43 #if defined(AFS_SUN5_ENV)
44 register proc_t *procp = ttoproc(curthread);
46 #if !defined(AFS_AIX41_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_SGI65_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_XBSD_ENV)
48 struct proc *procp = OSI_GET_CURRENT_PROCP();
50 struct proc *procp = u.u_procp;
51 #endif /* AFS_SGI_ENV */
54 #if defined(AFS_SGI65_ENV)
56 get_current_flid(&flid);
65 slp->sysid = u.u_sysid;
69 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV)
72 slp->pid = procp->p_pid;
74 slp->sysid = procp->p_sysid;
75 slp->pid = procp->p_epid;
78 #if defined(AFS_SGI_ENV)
80 slp->sysid = flid.fl_sysid;
82 slp->sysid = OSI_GET_CURRENT_SYSID();
86 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
89 #if defined(AFS_LINUX20_ENV) || defined(AFS_HPUX_ENV)
92 slp->pid = u.u_procp->p_pid;
95 #endif /* AFS_AIX_ENV */
96 #endif /* AFS_AIX32_ENV */
99 #if defined(AFS_AIX32_ENV)
102 flock->l_pid = getpid();
104 flock->l_sysid = u.u_sysid;
105 flock->l_pid = u.u_epid;
108 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV)
111 flock->l_pid = procp->p_pid;
113 flock->l_sysid = procp->p_sysid;
114 flock->l_pid = procp->p_epid;
117 #if defined(AFS_SGI_ENV)
119 flock->l_sysid = flid.fl_sysid;
121 flock->l_sysid = OSI_GET_CURRENT_SYSID();
125 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
128 #if defined(AFS_LINUX20_ENV) || defined(AFS_HPUX_ENV)
129 flock->l_pid = getpid();
131 flock->l_pid = u.u_procp->p_pid;
135 #endif /* AFS_AIX_ENV */
136 #endif /* AFS_AIX32_ENV */
140 /* return 1 (true) if specified flock does not match alp (if
141 * specified), or any of the slp structs (if alp == 0)
143 /* I'm not sure that the comparsion of flock->pid to p_ppid
144 * is correct. Should that be a comparision of alp (or slp) ->pid
145 * to p_ppid? Especially in the context of the lower loop, where
146 * the repeated comparison doesn't make much sense...
148 /* onlymine - don't match any locks which are held by my parent */
149 /* clid - only irix 6.5 */
152 lockIdcmp2(struct AFS_FLOCK *flock1, struct vcache *vp,
153 register struct SimpleLocks *alp, int onlymine, int clid)
155 register struct SimpleLocks *slp;
156 #if defined(AFS_SUN5_ENV)
157 register proc_t *procp = ttoproc(curthread);
159 #if !defined(AFS_AIX41_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_SGI65_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_XBSD_ENV)
161 struct proc *procp = curprocp;
162 #else /* AFS_SGI64_ENV */
163 struct proc *procp = u.u_procp;
164 #endif /* AFS_SGI64_ENV */
169 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
170 if (flock1->l_sysid != alp->sysid) {
174 if ((flock1->l_pid == alp->pid) ||
175 #if defined(AFS_AIX41_ENV) || defined(AFS_LINUX20_ENV) || defined(AFS_HPUX_ENV)
176 (!onlymine && (flock1->l_pid == getppid()))
178 #if defined(AFS_SGI65_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
179 /* XXX check this. used to be *only* irix for some reason. */
180 (!onlymine && (flock1->l_pid == clid))
182 (!onlymine && (flock1->l_pid == procp->p_ppid))
191 for (slp = vp->slocks; slp; slp = slp->next) {
192 #if defined(AFS_HAVE_FLOCK_SYSID)
193 if (flock1->l_sysid != slp->sysid) {
197 if (flock1->l_pid == slp->pid) {
201 return (1); /* failure */
205 /* we don't send multiple read flocks to the server, but rather just count
206 them up ourselves. Of course, multiple write locks are incompatible.
208 Note that we should always try to release a lock, even if we have
209 a network problem sending the release command through, since often
210 a lock is released on a close call, when the user can't retry anyway.
212 After we remove it from our structure, the lock will no longer be
213 kept alive, and the server should time it out within a few minutes.
215 94.04.13 add "force" parameter. If a child explicitly unlocks a
216 file, I guess we'll permit it. however, we don't want simple,
217 innocent closes by children to unlock files in the parent process.
219 /* clid - nonzero on sgi sunos osf1 only */
221 HandleFlock(register struct vcache *avc, int acom, struct vrequest *areq,
222 pid_t clid, int onlymine)
225 struct SimpleLocks *slp, *tlp, **slpp;
227 struct AFSVolSync tsync;
229 struct AFS_FLOCK flock;
231 AFS_STATCNT(HandleFlock);
232 code = 0; /* default when we don't make any network calls */
233 lockIdSet(&flock, NULL, clid);
235 #if defined(AFS_SGI_ENV)
236 osi_Assert(valusema(&avc->vc_rwlock) <= 0);
237 osi_Assert(OSI_GET_LOCKID() == avc->vc_rwlockid);
239 ObtainWriteLock(&avc->lock, 118);
240 if (acom & LOCK_UN) {
245 /* If the lock is held exclusive, then only the owning process
246 * or a child can unlock it. Use pid and ppid because they are
247 * unique identifiers.
249 if ((avc->flockCount < 0) && (getpid() != avc->ownslock)) {
251 if (onlymine || (getppid() != avc->ownslock)) {
253 if (onlymine || (u.u_procp->p_ppid != avc->ownslock)) {
255 ReleaseWriteLock(&avc->lock);
260 if (lockIdcmp2(&flock, avc, NULL, onlymine, clid)) {
261 ReleaseWriteLock(&avc->lock);
267 if (avc->flockCount == 0) {
268 ReleaseWriteLock(&avc->lock);
272 /* unlock the lock */
273 if (avc->flockCount > 0) {
275 for (slp = *slpp; slp;) {
276 if (!lockIdcmp2(&flock, avc, slp, onlymine, clid)) {
278 tlp = *slpp = slp->next;
279 osi_FreeSmallSpace(slp);
286 } else if (avc->flockCount == -1) {
287 afs_StoreAllSegments(avc, areq, AFS_ASYNC); /* fsync file early */
289 /* And remove the (only) exclusive lock entry from the list... */
290 osi_FreeSmallSpace(avc->slocks);
293 if (avc->flockCount == 0) {
295 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
297 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_RELEASELOCK);
299 code = RXAFS_ReleaseLock(tc->id, (struct AFSFid *)
300 &avc->fid.Fid, &tsync);
306 (tc, code, &avc->fid, areq,
307 AFS_STATS_FS_RPCIDX_RELEASELOCK, SHARED_LOCK, NULL));
310 while (1) { /* set a new lock */
312 * Upgrading from shared locks to Exclusive and vice versa
313 * is a bit tricky and we don't really support it yet. But
314 * we try to support the common used one which is upgrade
315 * a shared lock to an exclusive for the same process...
317 if ((avc->flockCount > 0 && (acom & LOCK_EX))
318 || (avc->flockCount == -1 && (acom & LOCK_SH))) {
320 * Upgrading from shared locks to an exclusive one:
321 * For now if all the shared locks belong to the
322 * same process then we unlock them on the server
323 * and proceed with the upgrade. Unless we change the
324 * server's locking interface impl we prohibit from
325 * unlocking other processes's shared locks...
326 * Upgrading from an exclusive lock to a shared one:
327 * Again only allowed to be done by the same process.
330 for (slp = *slpp; slp;) {
332 (&flock, avc, slp, 1 /*!onlymine */ , clid)) {
337 tlp = *slpp = slp->next;
338 osi_FreeSmallSpace(slp);
346 if (!code && avc->flockCount == 0) {
348 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
351 (AFS_STATS_FS_RPCIDX_RELEASELOCK);
354 RXAFS_ReleaseLock(tc->id,
355 (struct AFSFid *)&avc->fid.
362 (tc, code, &avc->fid, areq,
363 AFS_STATS_FS_RPCIDX_RELEASELOCK, SHARED_LOCK,
366 } else if (avc->flockCount == -1 && (acom & LOCK_EX)) {
367 if (lockIdcmp2(&flock, avc, NULL, 1, clid)) {
373 /* compatible here, decide if needs to go to file server. If
374 * we've already got the file locked (and thus read-locked, since
375 * we've already checked for compatibility), we shouldn't send
376 * the call through to the server again */
377 if (avc->flockCount == 0) {
378 /* we're the first on our block, send the call through */
379 lockType = ((acom & LOCK_EX) ? LockWrite : LockRead);
381 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
383 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETLOCK);
385 code = RXAFS_SetLock(tc->id, (struct AFSFid *)
386 &avc->fid.Fid, lockType,
393 (tc, code, &avc->fid, areq,
394 AFS_STATS_FS_RPCIDX_SETLOCK, SHARED_LOCK,
397 code = 0; /* otherwise, pretend things worked */
400 slp = (struct SimpleLocks *)
401 osi_AllocSmallSpace(sizeof(struct SimpleLocks));
402 if (acom & LOCK_EX) {
407 /* Record unique id of process owning exclusive lock. */
408 avc->ownslock = getpid();
411 slp->type = LockWrite;
414 avc->flockCount = -1;
416 slp->type = LockRead;
417 slp->next = avc->slocks;
422 lockIdSet(&flock, slp, clid);
425 /* now, if we got EWOULDBLOCK, and we're supposed to wait, we do */
426 if (((code == EWOULDBLOCK) || (code == EAGAIN) ||
427 (code == UAEWOULDBLOCK) || (code == UAEAGAIN))
428 && !(acom & LOCK_NB)) {
429 /* sleep for a second, allowing interrupts */
430 ReleaseWriteLock(&avc->lock);
431 #if defined(AFS_SGI_ENV)
432 AFS_RWUNLOCK((vnode_t *) avc, VRWLOCK_WRITE);
434 code = afs_osi_Wait(1000, NULL, 1);
435 #if defined(AFS_SGI_ENV)
436 AFS_RWLOCK((vnode_t *) avc, VRWLOCK_WRITE);
438 ObtainWriteLock(&avc->lock, 120);
440 code = EINTR; /* return this if ^C typed */
447 ReleaseWriteLock(&avc->lock);
448 code = afs_CheckCode(code, areq, 1); /* defeat a buggy AIX optimization */
453 /* warn a user that a lock has been ignored */
454 afs_int32 lastWarnTime = 0; /* this is used elsewhere */
458 register afs_int32 now;
461 AFS_STATCNT(DoLockWarning);
462 /* check if we've already warned someone recently */
463 if (now < lastWarnTime + 120)
466 /* otherwise, it is time to nag the user */
469 ("afs: byte-range lock/unlock ignored; make sure no one else is running this program.\n");
474 int afs_lockctl(struct vcache * avc, struct eflock * af, int flag,
475 struct AFS_UCRED * acred, pid_t clid, off_t offset)
476 #elif defined(AFS_SGI_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
477 int afs_lockctl(struct vcache * avc, struct AFS_FLOCK * af, int acmd,
478 struct AFS_UCRED * acred, pid_t clid)
481 int afs_lockctl(struct vcache * avc, struct AFS_FLOCK * af, int acmd,
482 struct AFS_UCRED * acred)
485 struct vrequest treq;
490 struct afs_fakestat_state fakestate;
492 AFS_STATCNT(afs_lockctl);
493 if ((code = afs_InitReq(&treq, acred)))
495 afs_InitFakeStat(&fakestate);
496 code = afs_EvalFakeStat(&avc, &fakestate, &treq);
498 afs_PutFakeStat(&fakestate);
502 if (flag & VNOFLCK) {
503 afs_PutFakeStat(&fakestate);
506 if (flag & CLNFLCK) {
508 } else if ((flag & GETFLCK) || (flag & RGETFLCK)) {
510 } else if ((flag & SETFLCK) || (flag & RSETFLCK)) {
514 #if (defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)) && !defined(AFS_SUN58_ENV)
515 if ((acmd == F_GETLK) || (acmd == F_RGETLK)) {
517 if (acmd == F_GETLK) {
519 if (af->l_type == F_UNLCK) {
520 afs_PutFakeStat(&fakestate);
523 #ifndef AFS_OSF_ENV /* getlock is a no-op for osf (for now) */
524 code = HandleGetLock(avc, af, &treq, clid);
526 code = afs_CheckCode(code, &treq, 2); /* defeat buggy AIX optimz */
527 afs_PutFakeStat(&fakestate);
529 } else if ((acmd == F_SETLK) || (acmd == F_SETLKW)
530 #if (defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)) && !defined(AFS_SUN58_ENV)
531 || (acmd == F_RSETLK) || (acmd == F_RSETLKW)) {
535 /* this next check is safer when left out, but more applications work
536 * with it in. However, they fail in race conditions. The question is
537 * what to do for people who don't have source to their application;
538 * this way at least, they can get work done */
539 #ifdef AFS_LINUX24_ENV
540 if (af->l_len == OFFSET_MAX)
541 af->l_len = 0; /* since some systems indicate it as EOF */
543 if (af->l_len == 0x7fffffff)
544 af->l_len = 0; /* since some systems indicate it as EOF */
545 #ifdef AFS_LINUX_64BIT_KERNEL
546 if (af->l_len == LONG_MAX)
547 af->l_len = 0; /* since some systems indicate it as EOF */
550 /* Java VMs ask for l_len=(long)-1 regardless of OS/CPU; bottom 32 bits
551 * sometimes get masked off by OS */
552 if ((af->l_len >> 32) == 0x7fffffff)
554 /* next line makes byte range locks always succeed,
555 * even when they should block */
556 if (af->l_whence != 0 || af->l_start != 0 || af->l_len != 0) {
558 afs_PutFakeStat(&fakestate);
561 /* otherwise we can turn this into a whole-file flock */
562 if (af->l_type == F_RDLCK)
564 else if (af->l_type == F_WRLCK)
566 else if (af->l_type == F_UNLCK)
569 afs_PutFakeStat(&fakestate);
570 return EINVAL; /* unknown lock type */
572 if (((acmd == F_SETLK)
573 #if (defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)) && !defined(AFS_SUN58_ENV)
574 || (acmd == F_RSETLK)
576 ) && code != LOCK_UN)
577 code |= LOCK_NB; /* non-blocking, s.v.p. */
578 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV)
579 code = HandleFlock(avc, code, &treq, clid, 0 /*!onlymine */ );
580 #elif defined(AFS_SGI_ENV)
581 AFS_RWLOCK((vnode_t *) avc, VRWLOCK_WRITE);
582 code = HandleFlock(avc, code, &treq, clid, 0 /*!onlymine */ );
583 AFS_RWUNLOCK((vnode_t *) avc, VRWLOCK_WRITE);
585 code = HandleFlock(avc, code, &treq, 0, 0 /*!onlymine */ );
587 code = afs_CheckCode(code, &treq, 3); /* defeat AIX -O bug */
588 afs_PutFakeStat(&fakestate);
591 afs_PutFakeStat(&fakestate);
597 * Get a description of the first lock which would
598 * block the lock specified. If the specified lock
599 * would succeed, fill in the lock structure with 'F_UNLCK'.
601 * To do that, we have to ask the server for the lock
603 * 1. The file is not locked by this machine.
604 * 2. Asking for write lock, and only the current
605 * PID has the file read locked.
607 #ifndef AFS_OSF_ENV /* getlock is a no-op for osf (for now) */
609 HandleGetLock(register struct vcache *avc, register struct AFS_FLOCK *af,
610 register struct vrequest *areq, int clid)
612 register afs_int32 code;
613 struct AFS_FLOCK flock;
615 lockIdSet(&flock, NULL, clid);
617 ObtainWriteLock(&avc->lock, 122);
618 if (avc->flockCount == 0) {
620 * We don't know ourselves, so ask the server. Unfortunately, we
621 * don't know the pid. Not even the server knows the pid. Besides,
622 * the process with the lock is on another machine
624 code = GetFlockCount(avc, areq);
625 if (code == 0 || (af->l_type == F_RDLCK && code > 0)) {
626 af->l_type = F_UNLCK;
630 af->l_type = F_RDLCK;
632 af->l_type = F_WRLCK;
635 #if defined(AFS_HAVE_FLOCK_SYSID)
641 if (af->l_type == F_RDLCK) {
643 * We want a read lock. If there are only
644 * read locks, or we are the one with the
645 * write lock, say it is unlocked.
647 if (avc->flockCount > 0 || /* only read locks */
648 !lockIdcmp2(&flock, avc, NULL, 1, clid)) {
649 af->l_type = F_UNLCK;
653 /* one write lock, but who? */
654 af->l_type = F_WRLCK; /* not us, so lock would block */
655 if (avc->slocks) { /* we know who, so tell */
656 af->l_pid = avc->slocks->pid;
657 #if defined(AFS_HAVE_FLOCK_SYSID)
658 af->l_sysid = avc->slocks->sysid;
661 af->l_pid = 0; /* XXX can't happen?? */
662 #if defined(AFS_HAVE_FLOCK_SYSID)
670 * Ok, we want a write lock. If there is a write lock
671 * already, and it is not this process, we fail.
673 if (avc->flockCount < 0) {
674 if (lockIdcmp2(&flock, avc, NULL, 1, clid)) {
675 af->l_type = F_WRLCK;
677 af->l_pid = avc->slocks->pid;
678 #if defined(AFS_HAVE_FLOCK_SYSID)
679 af->l_sysid = avc->slocks->sysid;
682 af->l_pid = 0; /* XXX can't happen?? */
683 #if defined(AFS_HAVE_FLOCK_SYSID)
689 /* we are the one with the write lock */
690 af->l_type = F_UNLCK;
695 * Want a write lock, and we know there are read locks.
696 * If there is more than one, or it isn't us, we cannot lock.
698 if ((avc->flockCount > 1)
699 || lockIdcmp2(&flock, avc, NULL, 1, clid)) {
700 struct SimpleLocks *slp;
702 af->l_type = F_RDLCK;
704 #if defined(AFS_HAVE_FLOCK_SYSID)
707 /* find a pid that isn't our own */
708 for (slp = avc->slocks; slp; slp = slp->next) {
709 if (lockIdcmp2(&flock, NULL, slp, 1, clid)) {
710 af->l_pid = slp->pid;
711 #if defined(AFS_HAVE_FLOCK_SYSID)
712 af->l_sysid = avc->slocks->sysid;
721 * Ok, we want a write lock. If there is a write lock
722 * already, and it is not this process, we fail.
724 if (avc->flockCount < 0) {
725 if (lockIdcmp2(&flock, avc, NULL, 1, clid)) {
726 af->l_type = F_WRLCK;
728 af->l_pid = avc->slocks->pid;
729 #if defined(AFS_HAVE_FLOCK_SYSID)
730 af->l_sysid = avc->slocks->sysid;
733 af->l_pid = 0; /* XXX can't happen?? */
734 #if defined(AFS_HAVE_FLOCK_SYSID)
740 /* we are the one with the write lock */
741 af->l_type = F_UNLCK;
746 * Want a write lock, and we know there are read locks.
747 * If there is more than one, or it isn't us, we cannot lock.
749 if ((avc->flockCount > 1)
750 || lockIdcmp2(&flock, avc, NULL, 1, clid)) {
751 struct SimpleLocks *slp;
752 af->l_type = F_RDLCK;
754 #if defined(AFS_HAVE_FLOCK_SYSID)
757 /* find a pid that isn't our own */
758 for (slp = avc->slocks; slp; slp = slp->next) {
759 if (lockIdcmp2(&flock, NULL, slp, 1, clid)) {
760 af->l_pid = slp->pid;
761 #if defined(AFS_HAVE_FLOCK_SYSID)
762 af->l_sysid = avc->slocks->sysid;
771 * Want a write lock, and there is just one read lock, and it
772 * is this process with a read lock. Ask the server if there
773 * are any more processes with the file locked.
775 code = GetFlockCount(avc, areq);
776 if (code == 0 || code == 1) {
777 af->l_type = F_UNLCK;
781 af->l_type = F_RDLCK;
783 af->l_type = F_WRLCK;
785 #if defined(AFS_HAVE_FLOCK_SYSID)
792 af->l_len = 0; /* to end of file */
795 ReleaseWriteLock(&avc->lock);
799 /* Get the 'flock' count from the server. This comes back in a 'spare'
800 * field from a GetStatus RPC. If we have any problems with the RPC,
801 * we lie and say the file is unlocked. If we ask any 'old' fileservers,
802 * the spare field will be a zero, saying the file is unlocked. This is
803 * OK, as a further 'lock' request will do the right thing.
806 GetFlockCount(struct vcache *avc, struct vrequest *areq)
808 register struct conn *tc;
809 register afs_int32 code;
810 struct AFSFetchStatus OutStatus;
811 struct AFSCallBack CallBack;
812 struct AFSVolSync tsync;
815 temp = areq->flags & O_NONBLOCK;
816 areq->flags |= O_NONBLOCK;
819 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
821 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHSTATUS);
824 RXAFS_FetchStatus(tc->id, (struct AFSFid *)&avc->fid.Fid,
825 &OutStatus, &CallBack, &tsync);
831 (tc, code, &avc->fid, areq, AFS_STATS_FS_RPCIDX_FETCHSTATUS,
835 areq->flags &= ~O_NONBLOCK;
838 return (0); /* failed, say it is 'unlocked' */
840 return ((int)OutStatus.lockCount);
846 #if !defined(AFS_AIX_ENV) && !defined(AFS_HPUX_ENV) && !defined(AFS_SUN5_ENV) && !defined(AFS_SGI_ENV) && !defined(UKERNEL) && !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_XBSD_ENV)
847 /* Flock not support on System V systems */
849 extern struct fileops afs_fileops;
852 afs_xflock(struct proc *p, void *args, int *retval)
853 #else /* AFS_OSF_ENV */
864 struct vrequest treq;
867 struct afs_fakestat_state fakestate;
869 afs_InitFakeStat(&fakestate);
870 AFS_STATCNT(afs_xflock);
873 uap = (struct a *)args;
874 getf(&fd, uap->fd, FILE_FLAGS_NULL, &u.u_file_state);
875 #else /* AFS_OSF_ENV */
876 uap = (struct a *)u.u_ap;
880 afs_PutFakeStat(&fakestate);
884 if (flockDone = afs_InitReq(&treq, u.u_cred)) {
885 afs_PutFakeStat(&fakestate);
888 /* first determine whether this is any sort of vnode */
889 if (fd->f_type == DTYPE_VNODE) {
890 /* good, this is a vnode; next see if it is an AFS vnode */
891 tvc = VTOAFS(fd->f_data); /* valid, given a vnode */
892 if (IsAfsVnode(AFSTOV(tvc))) {
893 /* This is an AFS vnode, so do the work */
894 code = afs_EvalFakeStat(&tvc, &fakestate, &treq);
896 afs_PutFakeStat(&fakestate);
899 if ((fd->f_flag & (FEXLOCK | FSHLOCK)) && !(uap->com & LOCK_UN)) {
900 /* First, if fd already has lock, release it for relock path */
901 #if defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV)
902 HandleFlock(tvc, LOCK_UN, &treq, u.u_procp->p_pid,
905 HandleFlock(tvc, LOCK_UN, &treq, 0, 0 /*!onlymine */ );
907 fd->f_flag &= ~(FEXLOCK | FSHLOCK);
909 /* now try the requested operation */
911 #if defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV)
913 HandleFlock(tvc, uap->com, &treq, u.u_procp->p_pid,
916 code = HandleFlock(tvc, uap->com, &treq, 0, 0 /*!onlymine */ );
922 if (uap->com & LOCK_UN) {
924 fd->f_flag &= ~(FEXLOCK | FSHLOCK);
928 #else /* AFS_OSF_ENV */
931 if (uap->com & LOCK_SH)
932 fd->f_flag |= FSHLOCK;
933 else if (uap->com & LOCK_EX)
934 fd->f_flag |= FEXLOCK;
938 fd->f_ops = &afs_fileops;
943 code = flock(p, args, retval);
949 afs_PutFakeStat(&fakestate);
951 #else /* AFS_OSF_ENV */
954 afs_PutFakeStat(&fakestate);
958 #endif /* !defined(AFS_AIX_ENV) && !defined(AFS_HPUX_ENV) && !defined(AFS_SUN5_ENV) && !defined(UKERNEL) && !defined(AFS_LINUX20_ENV) */