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"
20 #include "afs/sysincludes.h" /* Standard vendor system headers */
21 #include "afsincludes.h" /* Afs-based standard headers */
22 #include "afs/afs_stats.h" /* statistics */
23 #include "afs/afs_cbqueue.h"
24 #include "afs/nfsclient.h"
25 #include "afs/afs_osidnlc.h"
27 /* Static prototypes */
28 static int HandleGetLock(register struct vcache *avc,
29 register struct AFS_FLOCK *af, register struct vrequest *areq, int clid);
30 static int GetFlockCount(struct vcache *avc, struct vrequest *areq);
31 static int lockIdcmp2(struct AFS_FLOCK *flock1, struct vcache *vp,
32 register struct SimpleLocks *alp, int onlymine, int clid);
33 static void DoLockWarning(void);
35 /* int clid; * non-zero on SGI, OSF, SunOS, Darwin, xBSD ** XXX ptr type */
36 void lockIdSet(struct AFS_FLOCK *flock, struct SimpleLocks *slp, int clid)
38 #if defined(AFS_SUN5_ENV)
39 register proc_t *procp = ttoproc(curthread);
41 #if !defined(AFS_AIX41_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_SGI65_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_XBSD_ENV)
43 struct proc *procp = OSI_GET_CURRENT_PROCP();
45 struct proc *procp = u.u_procp;
46 #endif /* AFS_SGI_ENV */
49 #if defined(AFS_SGI65_ENV)
51 get_current_flid(&flid);
60 slp->sysid = u.u_sysid;
64 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV)
67 slp->pid = procp->p_pid;
69 slp->sysid = procp->p_sysid;
70 slp->pid = procp->p_epid;
73 #if defined(AFS_SGI_ENV)
75 slp->sysid = flid.fl_sysid;
77 slp->sysid = OSI_GET_CURRENT_SYSID();
81 #if defined(AFS_SUN_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
84 #if defined(AFS_LINUX20_ENV) || defined(AFS_HPUX_ENV)
87 slp->pid = u.u_procp->p_pid;
90 #endif /* AFS_AIX_ENV */
91 #endif /* AFS_AIX32_ENV */
94 #if defined(AFS_AIX32_ENV)
97 flock->l_pid = getpid();
99 flock->l_sysid = u.u_sysid;
100 flock->l_pid = u.u_epid;
103 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV)
106 flock->l_pid = procp->p_pid;
108 flock->l_sysid = procp->p_sysid;
109 flock->l_pid = procp->p_epid;
112 #if defined(AFS_SGI_ENV)
114 flock->l_sysid = flid.fl_sysid;
116 flock->l_sysid = OSI_GET_CURRENT_SYSID();
120 #if defined(AFS_SUN_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
123 #if defined(AFS_LINUX20_ENV) || defined(AFS_HPUX_ENV)
124 flock->l_pid = getpid();
126 flock->l_pid = u.u_procp->p_pid;
130 #endif /* AFS_AIX_ENV */
131 #endif /* AFS_AIX32_ENV */
135 /* return 1 (true) if specified flock does not match alp (if
136 * specified), or any of the slp structs (if alp == 0)
138 /* I'm not sure that the comparsion of flock->pid to p_ppid
139 * is correct. Should that be a comparision of alp (or slp) ->pid
140 * to p_ppid? Especially in the context of the lower loop, where
141 * the repeated comparison doesn't make much sense...
143 /* onlymine - don't match any locks which are held by my parent */
144 /* clid - only irix 6.5 */
146 static int lockIdcmp2(struct AFS_FLOCK *flock1, struct vcache *vp,
147 register struct SimpleLocks *alp, int onlymine, int clid)
149 register struct SimpleLocks *slp;
150 #if defined(AFS_SUN5_ENV)
151 register proc_t *procp = ttoproc(curthread);
153 #if !defined(AFS_AIX41_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_SGI65_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_XBSD_ENV)
155 struct proc *procp = curprocp;
156 #else /* AFS_SGI64_ENV */
157 struct proc *procp = u.u_procp;
158 #endif /* AFS_SGI64_ENV */
163 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
164 if (flock1->l_sysid != alp->sysid) {
168 if ((flock1->l_pid == alp->pid) ||
169 #if defined(AFS_AIX41_ENV) || defined(AFS_LINUX20_ENV) || defined(AFS_HPUX_ENV)
170 (!onlymine && (flock1->l_pid == getppid()))
172 #if defined(AFS_SGI65_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
173 /* XXX check this. used to be *only* irix for some reason. */
174 (!onlymine && (flock1->l_pid == clid))
176 (!onlymine && (flock1->l_pid == procp->p_ppid))
185 for (slp = vp->slocks; slp; slp = slp->next) {
186 #if defined(AFS_HAVE_FLOCK_SYSID)
187 if (flock1->l_sysid != slp->sysid) {
191 if (flock1->l_pid == slp->pid) {
195 return (1); /* failure */
199 /* we don't send multiple read flocks to the server, but rather just count
200 them up ourselves. Of course, multiple write locks are incompatible.
202 Note that we should always try to release a lock, even if we have
203 a network problem sending the release command through, since often
204 a lock is released on a close call, when the user can't retry anyway.
206 After we remove it from our structure, the lock will no longer be
207 kept alive, and the server should time it out within a few minutes.
209 94.04.13 add "force" parameter. If a child explicitly unlocks a
210 file, I guess we'll permit it. however, we don't want simple,
211 innocent closes by children to unlock files in the parent process.
213 /* clid - nonzero on sgi sunos osf1 only */
214 int HandleFlock(register struct vcache *avc, int acom,
215 struct vrequest *areq, pid_t clid, int onlymine)
218 struct SimpleLocks *slp, *tlp, **slpp;
220 struct AFSVolSync tsync;
222 struct AFS_FLOCK flock;
225 AFS_STATCNT(HandleFlock);
226 code = 0; /* default when we don't make any network calls */
227 lockIdSet(&flock, NULL, clid);
229 #if defined(AFS_SGI_ENV)
230 osi_Assert(valusema(&avc->vc_rwlock) <= 0);
231 osi_Assert(OSI_GET_LOCKID() == avc->vc_rwlockid);
233 ObtainWriteLock(&avc->lock,118);
234 if (acom & LOCK_UN) {
239 /* If the lock is held exclusive, then only the owning process
240 * or a child can unlock it. Use pid and ppid because they are
241 * unique identifiers.
243 if ((avc->flockCount < 0) && (getpid() != avc->ownslock)) {
245 if (onlymine || (getppid() != avc->ownslock)) {
247 if (onlymine || (u.u_procp->p_ppid != avc->ownslock)) {
249 ReleaseWriteLock(&avc->lock);
254 if (lockIdcmp2(&flock, avc, NULL, onlymine, clid)) {
255 ReleaseWriteLock(&avc->lock);
261 if (avc->flockCount == 0) {
262 ReleaseWriteLock(&avc->lock);
266 /* unlock the lock */
267 if (avc->flockCount > 0) {
269 for (slp = *slpp; slp;) {
270 if (!lockIdcmp2(&flock, avc, slp, onlymine, clid)) {
272 tlp = *slpp = slp->next;
273 osi_FreeSmallSpace(slp);
281 else if (avc->flockCount == -1) {
282 afs_StoreAllSegments(avc, areq, AFS_ASYNC); /* fsync file early */
284 /* And remove the (only) exclusive lock entry from the list... */
285 osi_FreeSmallSpace(avc->slocks);
288 if (avc->flockCount == 0) {
290 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
292 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_RELEASELOCK);
294 code = RXAFS_ReleaseLock(tc->id, (struct AFSFid *)
295 &avc->fid.Fid, &tsync);
301 (afs_Analyze(tc, code, &avc->fid, areq,
302 AFS_STATS_FS_RPCIDX_RELEASELOCK,
307 while (1) { /* set a new lock */
309 * Upgrading from shared locks to Exclusive and vice versa
310 * is a bit tricky and we don't really support it yet. But
311 * we try to support the common used one which is upgrade
312 * a shared lock to an exclusive for the same process...
314 if ((avc->flockCount > 0 && (acom & LOCK_EX)) ||
315 (avc->flockCount == -1 && (acom & LOCK_SH))) {
317 * Upgrading from shared locks to an exclusive one:
318 * For now if all the shared locks belong to the
319 * same process then we unlock them on the server
320 * and proceed with the upgrade. Unless we change the
321 * server's locking interface impl we prohibit from
322 * unlocking other processes's shared locks...
323 * Upgrading from an exclusive lock to a shared one:
324 * Again only allowed to be done by the same process.
327 for (slp = *slpp; slp;) {
328 if (!lockIdcmp2(&flock, avc, slp, 1/*!onlymine*/, clid)) {
333 tlp = *slpp = slp->next;
334 osi_FreeSmallSpace(slp);
342 if (!code && avc->flockCount == 0) {
344 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
346 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_RELEASELOCK);
348 code = RXAFS_ReleaseLock(tc->id,
349 (struct AFSFid *) &avc->fid.Fid,
356 (afs_Analyze(tc, code, &avc->fid, areq,
357 AFS_STATS_FS_RPCIDX_RELEASELOCK,
360 } else if (avc->flockCount == -1 && (acom & LOCK_EX)) {
361 if (lockIdcmp2(&flock, avc, NULL, 1, clid)) {
367 /* compatible here, decide if needs to go to file server. If
368 we've already got the file locked (and thus read-locked, since
369 we've already checked for compatibility), we shouldn't send
370 the call through to the server again */
371 if (avc->flockCount == 0) {
372 /* we're the first on our block, send the call through */
373 lockType = ((acom & LOCK_EX)? LockWrite : LockRead);
375 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
377 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETLOCK);
379 code = RXAFS_SetLock(tc->id, (struct AFSFid *)
380 &avc->fid.Fid, lockType, &tsync);
386 (afs_Analyze(tc, code, &avc->fid, areq,
387 AFS_STATS_FS_RPCIDX_SETLOCK,
390 else code = 0; /* otherwise, pretend things worked */
393 slp = (struct SimpleLocks *) osi_AllocSmallSpace(sizeof(struct SimpleLocks));
394 if (acom & LOCK_EX) {
399 /* Record unique id of process owning exclusive lock. */
400 avc->ownslock = getpid();
403 slp->type = LockWrite;
406 avc->flockCount = -1;
408 slp->type = LockRead;
409 slp->next = avc->slocks;
414 lockIdSet(&flock, slp, clid);
417 /* now, if we got EWOULDBLOCK, and we're supposed to wait, we do */
418 if(((code == EWOULDBLOCK)||(code == EAGAIN)) && !(acom & LOCK_NB)) {
419 /* sleep for a second, allowing interrupts */
420 ReleaseWriteLock(&avc->lock);
421 #if defined(AFS_SGI_ENV)
422 AFS_RWUNLOCK((vnode_t *)avc, VRWLOCK_WRITE);
424 code = afs_osi_Wait(1000, (struct afs_osi_WaitHandle *) 0, 1);
425 #if defined(AFS_SGI_ENV)
426 AFS_RWLOCK((vnode_t *)avc, VRWLOCK_WRITE);
428 ObtainWriteLock(&avc->lock,120);
430 code = EINTR; /* return this if ^C typed */
437 ReleaseWriteLock(&avc->lock);
438 code = afs_CheckCode(code, areq, 1); /* defeat a buggy AIX optimization */
443 /* warn a user that a lock has been ignored */
444 afs_int32 lastWarnTime = 0; /* this is used elsewhere */
445 static void DoLockWarning(void)
447 register afs_int32 now;
450 AFS_STATCNT(DoLockWarning);
451 /* check if we've already warned someone recently */
452 if (now < lastWarnTime + 120) return;
454 /* otherwise, it is time to nag the user */
456 afs_warn("afs: byte-range lock/unlock ignored; make sure no one else is running this program.\n");
461 afs_lockctl(struct vcache *avc, struct eflock *af, int flag,
462 struct AFS_UCRED *acred, pid_t clid, off_t offset)
464 #if defined(AFS_SGI_ENV) || (defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV)) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
465 afs_lockctl(struct vcache *avc, struct AFS_FLOCK *af, int acmd, struct AFS_UCRED *acred, pid_t clid)
468 afs_lockctl(struct vcache *avc, struct AFS_FLOCK *af, int acmd, struct AFS_UCRED *acred)
472 struct vrequest treq;
477 struct afs_fakestat_state fakestate;
479 AFS_STATCNT(afs_lockctl);
480 if ((code = afs_InitReq(&treq, acred))) return code;
481 afs_InitFakeStat(&fakestate);
482 code = afs_EvalFakeStat(&avc, &fakestate, &treq);
484 afs_PutFakeStat(&fakestate);
488 if (flag & VNOFLCK) {
489 afs_PutFakeStat(&fakestate);
492 if (flag & CLNFLCK) {
494 } else if ((flag & GETFLCK) || (flag & RGETFLCK)) {
496 } else if ((flag & SETFLCK) || (flag & RSETFLCK)) {
500 #if (defined(AFS_SUN_ENV) || defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)) && !defined(AFS_SUN58_ENV)
501 if ((acmd == F_GETLK) || (acmd == F_RGETLK)) {
503 if (acmd == F_GETLK) {
505 if (af->l_type == F_UNLCK) {
506 afs_PutFakeStat(&fakestate);
509 #ifndef AFS_OSF_ENV /* getlock is a no-op for osf (for now) */
510 code = HandleGetLock(avc, af, &treq, clid);
512 code = afs_CheckCode(code, &treq, 2); /* defeat buggy AIX optimz */
513 afs_PutFakeStat(&fakestate);
516 else if ((acmd == F_SETLK) || (acmd == F_SETLKW)
517 #if (defined(AFS_SUN_ENV) || defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)) && !defined(AFS_SUN58_ENV)
518 || (acmd == F_RSETLK)|| (acmd == F_RSETLKW)) {
522 /* this next check is safer when left out, but more applications work
523 with it in. However, they fail in race conditions. The question is
524 what to do for people who don't have source to their application;
525 this way at least, they can get work done */
526 #ifdef AFS_LINUX24_ENV
527 if (af->l_len == OFFSET_MAX)
528 af->l_len = 0; /* since some systems indicate it as EOF */
530 if (af->l_len == 0x7fffffff)
531 af->l_len = 0; /* since some systems indicate it as EOF */
532 #ifdef AFS_LINUX_64BIT_KERNEL
533 if (af->l_len == LONG_MAX)
534 af->l_len = 0; /* since some systems indicate it as EOF */
537 /* next line makes byte range locks always succeed,
538 even when they should block */
539 if (af->l_whence != 0 || af->l_start != 0 || af->l_len != 0) {
541 afs_PutFakeStat(&fakestate);
544 /* otherwise we can turn this into a whole-file flock */
545 if (af->l_type == F_RDLCK) code = LOCK_SH;
546 else if (af->l_type == F_WRLCK) code = LOCK_EX;
547 else if (af->l_type == F_UNLCK) code = LOCK_UN;
549 afs_PutFakeStat(&fakestate);
550 return EINVAL; /* unknown lock type */
552 if (((acmd == F_SETLK)
553 #if (defined(AFS_SGI_ENV) || defined(AFS_SUN_ENV)) && !defined(AFS_SUN58_ENV)
554 || (acmd == F_RSETLK)
556 ) && code != LOCK_UN)
557 code |= LOCK_NB; /* non-blocking, s.v.p. */
558 #if defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV)
559 code = HandleFlock(avc, code, &treq, clid, 0/*!onlymine*/);
561 #if defined(AFS_SGI_ENV)
562 AFS_RWLOCK((vnode_t *)avc, VRWLOCK_WRITE);
563 code = HandleFlock(avc, code, &treq, clid, 0/*!onlymine*/);
564 AFS_RWUNLOCK((vnode_t *)avc, VRWLOCK_WRITE);
566 code = HandleFlock(avc, code, &treq, 0, 0/*!onlymine*/);
569 code = afs_CheckCode(code, &treq, 3); /* defeat AIX -O bug */
570 afs_PutFakeStat(&fakestate);
573 afs_PutFakeStat(&fakestate);
579 * Get a description of the first lock which would
580 * block the lock specified. If the specified lock
581 * would succeed, fill in the lock structure with 'F_UNLCK'.
583 * To do that, we have to ask the server for the lock
585 * 1. The file is not locked by this machine.
586 * 2. Asking for write lock, and only the current
587 * PID has the file read locked.
589 #ifndef AFS_OSF_ENV /* getlock is a no-op for osf (for now) */
590 static int HandleGetLock(register struct vcache *avc,
591 register struct AFS_FLOCK *af, register struct vrequest *areq, int clid)
593 register afs_int32 code;
594 struct AFS_FLOCK flock;
596 lockIdSet(&flock, NULL, clid);
598 ObtainWriteLock(&avc->lock,122);
599 if (avc->flockCount == 0) {
600 /* We don't know ourselves, so ask the server. Unfortunately, we don't know the pid.
601 * Not even the server knows the pid. Besides, the process with the lock is on another machine
603 code = GetFlockCount(avc, areq);
604 if (code == 0 || (af->l_type == F_RDLCK && code > 0)) {
605 af->l_type = F_UNLCK;
609 af->l_type = F_RDLCK;
611 af->l_type = F_WRLCK;
614 #if defined(AFS_HAVE_FLOCK_SYSID)
620 if (af->l_type == F_RDLCK) {
622 * We want a read lock. If there are only
623 * read locks, or we are the one with the
624 * write lock, say it is unlocked.
626 if (avc->flockCount > 0 || /* only read locks */
627 !lockIdcmp2(&flock, avc, NULL, 1, clid)) {
628 af->l_type = F_UNLCK;
632 /* one write lock, but who? */
633 af->l_type = F_WRLCK; /* not us, so lock would block */
634 if (avc->slocks) { /* we know who, so tell */
635 af->l_pid = avc->slocks->pid;
636 #if defined(AFS_HAVE_FLOCK_SYSID)
637 af->l_sysid = avc->slocks->sysid;
640 af->l_pid = 0; /* XXX can't happen?? */
641 #if defined(AFS_HAVE_FLOCK_SYSID)
649 * Ok, we want a write lock. If there is a write lock
650 * already, and it is not this process, we fail.
652 if (avc->flockCount < 0) {
653 if (lockIdcmp2(&flock, avc, NULL, 1, clid)) {
654 af->l_type = F_WRLCK;
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)
668 /* we are the one with the write lock */
669 af->l_type = F_UNLCK;
674 * Want a write lock, and we know there are read locks.
675 * If there is more than one, or it isn't us, we cannot lock.
677 if ((avc->flockCount > 1)
678 || lockIdcmp2(&flock, avc, NULL, 1, clid)) {
679 struct SimpleLocks *slp;
681 af->l_type = F_RDLCK;
683 #if defined(AFS_HAVE_FLOCK_SYSID)
686 /* find a pid that isn't our own */
687 for (slp = avc->slocks; slp; slp = slp->next) {
688 if (lockIdcmp2(&flock, NULL, slp, 1, clid)) {
689 af->l_pid = slp->pid;
690 #if defined(AFS_HAVE_FLOCK_SYSID)
691 af->l_sysid = avc->slocks->sysid;
700 * Ok, we want a write lock. If there is a write lock
701 * already, and it is not this process, we fail.
703 if (avc->flockCount < 0) {
704 if (lockIdcmp2(&flock, avc, NULL, 1, clid)) {
705 af->l_type = F_WRLCK;
707 af->l_pid = avc->slocks->pid;
708 #if defined(AFS_HAVE_FLOCK_SYSID)
709 af->l_sysid = avc->slocks->sysid;
712 af->l_pid = 0; /* XXX can't happen?? */
713 #if defined(AFS_HAVE_FLOCK_SYSID)
719 /* we are the one with the write lock */
720 af->l_type = F_UNLCK;
725 * Want a write lock, and we know there are read locks.
726 * If there is more than one, or it isn't us, we cannot lock.
728 if ((avc->flockCount > 1)
729 || lockIdcmp2(&flock, avc, NULL, 1, clid)) {
730 struct SimpleLocks *slp;
731 af->l_type = F_RDLCK;
733 #if defined(AFS_HAVE_FLOCK_SYSID)
736 /* find a pid that isn't our own */
737 for (slp = avc->slocks; slp; slp = slp->next) {
738 if (lockIdcmp2(&flock, NULL, slp, 1, clid)) {
739 af->l_pid = slp->pid;
740 #if defined(AFS_HAVE_FLOCK_SYSID)
741 af->l_sysid = avc->slocks->sysid;
750 * Want a write lock, and there is just one read lock, and it
751 * is this process with a read lock. Ask the server if there
752 * are any more processes with the file locked.
754 code = GetFlockCount(avc, areq);
755 if (code == 0 || code == 1) {
756 af->l_type = F_UNLCK;
760 af->l_type = F_RDLCK;
762 af->l_type = F_WRLCK;
764 #if defined(AFS_HAVE_FLOCK_SYSID)
771 af->l_len = 0; /* to end of file */
774 ReleaseWriteLock(&avc->lock);
778 /* Get the 'flock' count from the server. This comes back in a 'spare'
779 * field from a GetStatus RPC. If we have any problems with the RPC,
780 * we lie and say the file is unlocked. If we ask any 'old' fileservers,
781 * the spare field will be a zero, saying the file is unlocked. This is
782 * OK, as a further 'lock' request will do the right thing.
784 static int GetFlockCount(struct vcache *avc, struct vrequest *areq)
786 register struct conn *tc;
787 register afs_int32 code;
788 struct AFSFetchStatus OutStatus;
789 struct AFSCallBack CallBack;
790 struct AFSVolSync tsync;
794 temp = areq->flags & O_NONBLOCK;
795 areq->flags |= O_NONBLOCK;
798 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
800 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHSTATUS);
802 code = RXAFS_FetchStatus(tc->id, (struct AFSFid *) &avc->fid.Fid,
803 &OutStatus, &CallBack, &tsync);
808 (afs_Analyze(tc, code, &avc->fid, areq,
809 AFS_STATS_FS_RPCIDX_FETCHSTATUS,
813 areq->flags &= ~O_NONBLOCK;
816 return(0); /* failed, say it is 'unlocked' */
818 return((int)OutStatus.lockCount);
824 #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)
825 /* Flock not support on System V systems */
827 extern struct fileops afs_fileops;
829 int afs_xflock (struct proc *p, void *args, int *retval)
830 #else /* AFS_OSF_ENV */
831 int afs_xflock (void)
840 struct vrequest treq;
843 struct afs_fakestat_state fakestate;
845 afs_InitFakeStat(&fakestate);
846 AFS_STATCNT(afs_xflock);
849 uap = (struct a *)args;
850 getf(&fd, uap->fd, FILE_FLAGS_NULL, &u.u_file_state);
851 #else /* AFS_OSF_ENV */
852 uap = (struct a *)u.u_ap;
856 afs_PutFakeStat(&fakestate);
860 if (flockDone = afs_InitReq(&treq, u.u_cred)) {
861 afs_PutFakeStat(&fakestate);
864 /* first determine whether this is any sort of vnode */
865 if (fd->f_type == DTYPE_VNODE) {
866 /* good, this is a vnode; next see if it is an AFS vnode */
867 tvc = VTOAFS(fd->f_data); /* valid, given a vnode */
868 if (IsAfsVnode(AFSTOV(tvc))) {
869 /* This is an AFS vnode, so do the work */
871 /* find real vcache entry; shouldn't be null if gnode ref count
874 tvc = VTOAFS(afs_gntovn)(tvc);
877 afs_PutFakeStat(&fakestate);
881 code = afs_EvalFakeStat(&tvc, &fakestate, &treq);
883 afs_PutFakeStat(&fakestate);
886 if ((fd->f_flag & (FEXLOCK | FSHLOCK)) && !(uap->com & LOCK_UN)) {
887 /* First, if fd already has lock, release it for relock path */
888 #if defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV) || (defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV))
889 HandleFlock(tvc, LOCK_UN, &treq, u.u_procp->p_pid, 0/*!onlymine*/);
891 HandleFlock(tvc, LOCK_UN, &treq, 0, 0/*!onlymine*/);
893 fd->f_flag &= ~(FEXLOCK | FSHLOCK);
895 /* now try the requested operation */
897 #if defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV) || (defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV))
898 code = HandleFlock(tvc, uap->com, &treq,
899 u.u_procp->p_pid, 0/*!onlymine*/);
901 code = HandleFlock(tvc, uap->com, &treq, 0, 0/*!onlymine*/);
907 if (uap->com & LOCK_UN) {
909 fd->f_flag &= ~(FEXLOCK | FSHLOCK);
914 #else /* AFS_OSF_ENV */
917 if (uap->com & LOCK_SH) fd->f_flag |= FSHLOCK;
918 else if (uap->com & LOCK_EX) fd->f_flag |= FEXLOCK;
922 fd->f_ops = &afs_fileops;
927 code = flock(p, args, retval);
933 afs_PutFakeStat(&fakestate);
935 #else /* AFS_OSF_ENV */
938 (*afs_longcall_procs.LC_flock)();
942 afs_PutFakeStat(&fakestate);
946 #endif /* !defined(AFS_AIX_ENV) && !defined(AFS_HPUX_ENV) && !defined(AFS_SUN5_ENV) && !defined(UKERNEL) && !defined(AFS_LINUX20_ENV) */