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, NULL, 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)
463 #elif defined(AFS_SGI_ENV) || (defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV)) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
464 afs_lockctl(struct vcache *avc, struct AFS_FLOCK *af, int acmd, struct AFS_UCRED *acred, pid_t clid)
467 afs_lockctl(struct vcache *avc, struct AFS_FLOCK *af, int acmd, struct AFS_UCRED *acred)
470 struct vrequest treq;
475 struct afs_fakestat_state fakestate;
477 AFS_STATCNT(afs_lockctl);
478 if ((code = afs_InitReq(&treq, acred))) return code;
479 afs_InitFakeStat(&fakestate);
480 code = afs_EvalFakeStat(&avc, &fakestate, &treq);
482 afs_PutFakeStat(&fakestate);
486 if (flag & VNOFLCK) {
487 afs_PutFakeStat(&fakestate);
490 if (flag & CLNFLCK) {
492 } else if ((flag & GETFLCK) || (flag & RGETFLCK)) {
494 } else if ((flag & SETFLCK) || (flag & RSETFLCK)) {
498 #if (defined(AFS_SUN_ENV) || defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)) && !defined(AFS_SUN58_ENV)
499 if ((acmd == F_GETLK) || (acmd == F_RGETLK)) {
501 if (acmd == F_GETLK) {
503 if (af->l_type == F_UNLCK) {
504 afs_PutFakeStat(&fakestate);
507 #ifndef AFS_OSF_ENV /* getlock is a no-op for osf (for now) */
508 code = HandleGetLock(avc, af, &treq, clid);
510 code = afs_CheckCode(code, &treq, 2); /* defeat buggy AIX optimz */
511 afs_PutFakeStat(&fakestate);
514 else if ((acmd == F_SETLK) || (acmd == F_SETLKW)
515 #if (defined(AFS_SUN_ENV) || defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)) && !defined(AFS_SUN58_ENV)
516 || (acmd == F_RSETLK)|| (acmd == F_RSETLKW)) {
520 /* this next check is safer when left out, but more applications work
521 with it in. However, they fail in race conditions. The question is
522 what to do for people who don't have source to their application;
523 this way at least, they can get work done */
524 #ifdef AFS_LINUX24_ENV
525 if (af->l_len == OFFSET_MAX)
526 af->l_len = 0; /* since some systems indicate it as EOF */
528 if (af->l_len == 0x7fffffff)
529 af->l_len = 0; /* since some systems indicate it as EOF */
530 #ifdef AFS_LINUX_64BIT_KERNEL
531 if (af->l_len == LONG_MAX)
532 af->l_len = 0; /* since some systems indicate it as EOF */
535 /* next line makes byte range locks always succeed,
536 even when they should block */
537 if (af->l_whence != 0 || af->l_start != 0 || af->l_len != 0) {
539 afs_PutFakeStat(&fakestate);
542 /* otherwise we can turn this into a whole-file flock */
543 if (af->l_type == F_RDLCK) code = LOCK_SH;
544 else if (af->l_type == F_WRLCK) code = LOCK_EX;
545 else if (af->l_type == F_UNLCK) code = LOCK_UN;
547 afs_PutFakeStat(&fakestate);
548 return EINVAL; /* unknown lock type */
550 if (((acmd == F_SETLK)
551 #if (defined(AFS_SGI_ENV) || defined(AFS_SUN_ENV)) && !defined(AFS_SUN58_ENV)
552 || (acmd == F_RSETLK)
554 ) && code != LOCK_UN)
555 code |= LOCK_NB; /* non-blocking, s.v.p. */
556 #if (defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV)) || defined(AFS_OSF_ENV)
557 code = HandleFlock(avc, code, &treq, clid, 0/*!onlymine*/);
558 #elif defined(AFS_SGI_ENV)
559 AFS_RWLOCK((vnode_t *)avc, VRWLOCK_WRITE);
560 code = HandleFlock(avc, code, &treq, clid, 0/*!onlymine*/);
561 AFS_RWUNLOCK((vnode_t *)avc, VRWLOCK_WRITE);
563 code = HandleFlock(avc, code, &treq, 0, 0/*!onlymine*/);
565 code = afs_CheckCode(code, &treq, 3); /* defeat AIX -O bug */
566 afs_PutFakeStat(&fakestate);
569 afs_PutFakeStat(&fakestate);
575 * Get a description of the first lock which would
576 * block the lock specified. If the specified lock
577 * would succeed, fill in the lock structure with 'F_UNLCK'.
579 * To do that, we have to ask the server for the lock
581 * 1. The file is not locked by this machine.
582 * 2. Asking for write lock, and only the current
583 * PID has the file read locked.
585 #ifndef AFS_OSF_ENV /* getlock is a no-op for osf (for now) */
586 static int HandleGetLock(register struct vcache *avc,
587 register struct AFS_FLOCK *af, register struct vrequest *areq, int clid)
589 register afs_int32 code;
590 struct AFS_FLOCK flock;
592 lockIdSet(&flock, NULL, clid);
594 ObtainWriteLock(&avc->lock,122);
595 if (avc->flockCount == 0) {
597 * We don't know ourselves, so ask the server. Unfortunately, we
598 * don't know the pid. Not even the server knows the pid. Besides,
599 * the process with the lock is on another machine
601 code = GetFlockCount(avc, areq);
602 if (code == 0 || (af->l_type == F_RDLCK && code > 0)) {
603 af->l_type = F_UNLCK;
607 af->l_type = F_RDLCK;
609 af->l_type = F_WRLCK;
612 #if defined(AFS_HAVE_FLOCK_SYSID)
618 if (af->l_type == F_RDLCK) {
620 * We want a read lock. If there are only
621 * read locks, or we are the one with the
622 * write lock, say it is unlocked.
624 if (avc->flockCount > 0 || /* only read locks */
625 !lockIdcmp2(&flock, avc, NULL, 1, clid)) {
626 af->l_type = F_UNLCK;
630 /* one write lock, but who? */
631 af->l_type = F_WRLCK; /* not us, so lock would block */
632 if (avc->slocks) { /* we know who, so tell */
633 af->l_pid = avc->slocks->pid;
634 #if defined(AFS_HAVE_FLOCK_SYSID)
635 af->l_sysid = avc->slocks->sysid;
638 af->l_pid = 0; /* XXX can't happen?? */
639 #if defined(AFS_HAVE_FLOCK_SYSID)
647 * Ok, we want a write lock. If there is a write lock
648 * already, and it is not this process, we fail.
650 if (avc->flockCount < 0) {
651 if (lockIdcmp2(&flock, avc, NULL, 1, clid)) {
652 af->l_type = F_WRLCK;
654 af->l_pid = avc->slocks->pid;
655 #if defined(AFS_HAVE_FLOCK_SYSID)
656 af->l_sysid = avc->slocks->sysid;
659 af->l_pid = 0; /* XXX can't happen?? */
660 #if defined(AFS_HAVE_FLOCK_SYSID)
666 /* we are the one with the write lock */
667 af->l_type = F_UNLCK;
672 * Want a write lock, and we know there are read locks.
673 * If there is more than one, or it isn't us, we cannot lock.
675 if ((avc->flockCount > 1)
676 || lockIdcmp2(&flock, avc, NULL, 1, clid)) {
677 struct SimpleLocks *slp;
679 af->l_type = F_RDLCK;
681 #if defined(AFS_HAVE_FLOCK_SYSID)
684 /* find a pid that isn't our own */
685 for (slp = avc->slocks; slp; slp = slp->next) {
686 if (lockIdcmp2(&flock, NULL, slp, 1, clid)) {
687 af->l_pid = slp->pid;
688 #if defined(AFS_HAVE_FLOCK_SYSID)
689 af->l_sysid = avc->slocks->sysid;
698 * Ok, we want a write lock. If there is a write lock
699 * already, and it is not this process, we fail.
701 if (avc->flockCount < 0) {
702 if (lockIdcmp2(&flock, avc, NULL, 1, clid)) {
703 af->l_type = F_WRLCK;
705 af->l_pid = avc->slocks->pid;
706 #if defined(AFS_HAVE_FLOCK_SYSID)
707 af->l_sysid = avc->slocks->sysid;
710 af->l_pid = 0; /* XXX can't happen?? */
711 #if defined(AFS_HAVE_FLOCK_SYSID)
717 /* we are the one with the write lock */
718 af->l_type = F_UNLCK;
723 * Want a write lock, and we know there are read locks.
724 * If there is more than one, or it isn't us, we cannot lock.
726 if ((avc->flockCount > 1)
727 || lockIdcmp2(&flock, avc, NULL, 1, clid)) {
728 struct SimpleLocks *slp;
729 af->l_type = F_RDLCK;
731 #if defined(AFS_HAVE_FLOCK_SYSID)
734 /* find a pid that isn't our own */
735 for (slp = avc->slocks; slp; slp = slp->next) {
736 if (lockIdcmp2(&flock, NULL, slp, 1, clid)) {
737 af->l_pid = slp->pid;
738 #if defined(AFS_HAVE_FLOCK_SYSID)
739 af->l_sysid = avc->slocks->sysid;
748 * Want a write lock, and there is just one read lock, and it
749 * is this process with a read lock. Ask the server if there
750 * are any more processes with the file locked.
752 code = GetFlockCount(avc, areq);
753 if (code == 0 || code == 1) {
754 af->l_type = F_UNLCK;
758 af->l_type = F_RDLCK;
760 af->l_type = F_WRLCK;
762 #if defined(AFS_HAVE_FLOCK_SYSID)
769 af->l_len = 0; /* to end of file */
772 ReleaseWriteLock(&avc->lock);
776 /* Get the 'flock' count from the server. This comes back in a 'spare'
777 * field from a GetStatus RPC. If we have any problems with the RPC,
778 * we lie and say the file is unlocked. If we ask any 'old' fileservers,
779 * the spare field will be a zero, saying the file is unlocked. This is
780 * OK, as a further 'lock' request will do the right thing.
782 static int GetFlockCount(struct vcache *avc, struct vrequest *areq)
784 register struct conn *tc;
785 register afs_int32 code;
786 struct AFSFetchStatus OutStatus;
787 struct AFSCallBack CallBack;
788 struct AFSVolSync tsync;
792 temp = areq->flags & O_NONBLOCK;
793 areq->flags |= O_NONBLOCK;
796 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
798 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHSTATUS);
800 code = RXAFS_FetchStatus(tc->id, (struct AFSFid *) &avc->fid.Fid,
801 &OutStatus, &CallBack, &tsync);
806 (afs_Analyze(tc, code, &avc->fid, areq,
807 AFS_STATS_FS_RPCIDX_FETCHSTATUS,
811 areq->flags &= ~O_NONBLOCK;
814 return(0); /* failed, say it is 'unlocked' */
816 return((int)OutStatus.lockCount);
822 #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)
823 /* Flock not support on System V systems */
825 extern struct fileops afs_fileops;
827 int afs_xflock (struct proc *p, void *args, int *retval)
828 #else /* AFS_OSF_ENV */
829 int afs_xflock (void)
838 struct vrequest treq;
841 struct afs_fakestat_state fakestate;
843 afs_InitFakeStat(&fakestate);
844 AFS_STATCNT(afs_xflock);
847 uap = (struct a *)args;
848 getf(&fd, uap->fd, FILE_FLAGS_NULL, &u.u_file_state);
849 #else /* AFS_OSF_ENV */
850 uap = (struct a *)u.u_ap;
854 afs_PutFakeStat(&fakestate);
858 if (flockDone = afs_InitReq(&treq, u.u_cred)) {
859 afs_PutFakeStat(&fakestate);
862 /* first determine whether this is any sort of vnode */
863 if (fd->f_type == DTYPE_VNODE) {
864 /* good, this is a vnode; next see if it is an AFS vnode */
865 tvc = VTOAFS(fd->f_data); /* valid, given a vnode */
866 if (IsAfsVnode(AFSTOV(tvc))) {
867 /* This is an AFS vnode, so do the work */
869 /* find real vcache entry; shouldn't be null if gnode ref count
872 tvc = VTOAFS(afs_gntovn)(tvc);
875 afs_PutFakeStat(&fakestate);
879 code = afs_EvalFakeStat(&tvc, &fakestate, &treq);
881 afs_PutFakeStat(&fakestate);
884 if ((fd->f_flag & (FEXLOCK | FSHLOCK)) && !(uap->com & LOCK_UN)) {
885 /* First, if fd already has lock, release it for relock path */
886 #if defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV) || (defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV))
887 HandleFlock(tvc, LOCK_UN, &treq, u.u_procp->p_pid, 0/*!onlymine*/);
889 HandleFlock(tvc, LOCK_UN, &treq, 0, 0/*!onlymine*/);
891 fd->f_flag &= ~(FEXLOCK | FSHLOCK);
893 /* now try the requested operation */
895 #if defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV) || (defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV))
896 code = HandleFlock(tvc, uap->com, &treq,
897 u.u_procp->p_pid, 0/*!onlymine*/);
899 code = HandleFlock(tvc, uap->com, &treq, 0, 0/*!onlymine*/);
905 if (uap->com & LOCK_UN) {
907 fd->f_flag &= ~(FEXLOCK | FSHLOCK);
912 #else /* AFS_OSF_ENV */
915 if (uap->com & LOCK_SH) fd->f_flag |= FSHLOCK;
916 else if (uap->com & LOCK_EX) fd->f_flag |= FEXLOCK;
920 fd->f_ops = &afs_fileops;
925 code = flock(p, args, retval);
931 afs_PutFakeStat(&fakestate);
933 #else /* AFS_OSF_ENV */
936 (*afs_longcall_procs.LC_flock)();
940 afs_PutFakeStat(&fakestate);
944 #endif /* !defined(AFS_AIX_ENV) && !defined(AFS_HPUX_ENV) && !defined(AFS_SUN5_ENV) && !defined(UKERNEL) && !defined(AFS_LINUX20_ENV) */