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"
19 #include "afs/sysincludes.h" /* Standard vendor system headers */
20 #include "afsincludes.h" /* Afs-based standard headers */
21 #include "afs/afs_stats.h" /* statistics */
22 #include "afs/afs_cbqueue.h"
23 #include "afs/nfsclient.h"
24 #include "afs/afs_osidnlc.h"
25 #include "afs/unified_afs.h"
31 /* Static prototypes */
32 static int HandleGetLock(register struct vcache *avc,
33 register struct AFS_FLOCK *af,
34 register struct vrequest *areq, int clid);
35 static int GetFlockCount(struct vcache *avc, struct vrequest *areq);
36 static int lockIdcmp2(struct AFS_FLOCK *flock1, struct vcache *vp,
37 register struct SimpleLocks *alp, int onlymine,
39 static void DoLockWarning(void);
41 /* int clid; * non-zero on SGI, OSF, SunOS, Darwin, xBSD ** XXX ptr type */
43 #if defined(AFS_SUN5_ENV)
45 lockIdSet(struct AFS_FLOCK *flock, struct SimpleLocks *slp, int clid)
47 proc_t *procp = ttoproc(curthread);
52 slp->pid = procp->p_pid;
54 slp->sysid = procp->p_sysid;
55 slp->pid = procp->p_epid;
60 flock->l_pid = procp->p_pid;
62 flock->l_sysid = procp->p_sysid;
63 flock->l_pid = procp->p_epid;
67 #elif defined(AFS_SGI_ENV)
69 lockIdSet(struct AFS_FLOCK *flock, struct SimpleLocks *slp, int clid)
71 # if defined(AFS_SGI65_ENV)
73 get_current_flid(&flid);
75 afs_proc_t *procp = OSI_GET_CURRENT_PROCP();
80 slp->sysid = flid.fl_sysid;
82 slp->sysid = OSI_GET_CURRENT_SYSID();
87 flock->l_sysid = flid.fl_sysid;
89 flock->l_sysid = OSI_GET_CURRENT_SYSID();
94 #elif defined(AFS_AIX_ENV)
96 lockIdSet(struct AFS_FLOCK *flock, struct SimpleLocks *slp, int clid)
98 # if !defined(AFS_AIX32_ENV)
99 afs_proc_t *procp = u.u_procp;
103 # if defined(AFS_AIX41_ENV)
106 # elif defined(AFS_AIX32_ENV)
107 slp->sysid = u.u_sysid;
110 slp->sysid = procp->p_sysid;
111 slp->pid = prcop->p_epid;
114 # if defined(AFS_AIX41_ENV)
116 flock->l_pid = getpid();
117 # elif defined(AFS_AIX32_ENV)
118 flock->l_sysid = u.u_sysid;
119 flock->l_pid = u.u_epid;
121 flock->l_sysid = procp->p_sysid;
122 flock->l_pid = procp->p_epid;
125 #elif defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
127 lockIdSet(struct AFS_FLOCK *flock, struct SimpleLocks *slp, int clid)
135 #elif defined(AFS_LINUX20_ENV) || defined(AFS_HPUX_ENV)
137 lockIdSet(struct AFS_FLOCK *flock, struct SimpleLocks *slp, int clid)
142 flock->l_pid = getpid();
147 lockIdSet(struct AFS_FLOCK *flock, struct SimpleLocks *slp, int clid)
150 slp->pid = u.u_procp->p_pid;
152 flock->l_pid = u.u_procp->p_pid;
157 /* return 1 (true) if specified flock does not match alp (if
158 * specified), or any of the slp structs (if alp == 0)
160 /* I'm not sure that the comparsion of flock->pid to p_ppid
161 * is correct. Should that be a comparision of alp (or slp) ->pid
162 * to p_ppid? Especially in the context of the lower loop, where
163 * the repeated comparison doesn't make much sense...
165 /* onlymine - don't match any locks which are held by my parent */
166 /* clid - only irix 6.5 */
169 lockIdcmp2(struct AFS_FLOCK *flock1, struct vcache *vp,
170 register struct SimpleLocks *alp, int onlymine, int clid)
172 register struct SimpleLocks *slp;
173 #if defined(AFS_SUN5_ENV)
174 register proc_t *procp = ttoproc(curthread);
176 #if !defined(AFS_AIX41_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_SGI65_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_XBSD_ENV)
178 afs_proc_t *procp = curprocp;
179 #else /* AFS_SGI64_ENV */
180 afs_proc_t *procp = u.u_procp;
181 #endif /* AFS_SGI64_ENV */
186 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
187 if (flock1->l_sysid != alp->sysid) {
191 if ((flock1->l_pid == alp->pid) ||
192 #if defined(AFS_AIX41_ENV) || defined(AFS_LINUX20_ENV) || defined(AFS_HPUX_ENV)
193 (!onlymine && (flock1->l_pid == getppid()))
195 #if defined(AFS_SGI65_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
196 /* XXX check this. used to be *only* irix for some reason. */
197 (!onlymine && (flock1->l_pid == clid))
199 (!onlymine && (flock1->l_pid == procp->p_ppid))
208 for (slp = vp->slocks; slp; slp = slp->next) {
209 #if defined(AFS_HAVE_FLOCK_SYSID)
210 if (flock1->l_sysid != slp->sysid) {
214 if (flock1->l_pid == slp->pid) {
218 return (1); /* failure */
222 /* we don't send multiple read flocks to the server, but rather just count
223 them up ourselves. Of course, multiple write locks are incompatible.
225 Note that we should always try to release a lock, even if we have
226 a network problem sending the release command through, since often
227 a lock is released on a close call, when the user can't retry anyway.
229 After we remove it from our structure, the lock will no longer be
230 kept alive, and the server should time it out within a few minutes.
232 94.04.13 add "force" parameter. If a child explicitly unlocks a
233 file, I guess we'll permit it. however, we don't want simple,
234 innocent closes by children to unlock files in the parent process.
236 If called when disconnected support is unabled, the discon_lock must
239 /* clid - nonzero on sgi sunos osf1 only */
241 HandleFlock(register struct vcache *avc, int acom, struct vrequest *areq,
242 pid_t clid, int onlymine)
245 struct SimpleLocks *slp, *tlp, **slpp;
247 struct AFSVolSync tsync;
249 struct AFS_FLOCK flock;
251 AFS_STATCNT(HandleFlock);
252 code = 0; /* default when we don't make any network calls */
253 lockIdSet(&flock, NULL, clid);
255 #if defined(AFS_SGI_ENV)
256 osi_Assert(valusema(&avc->vc_rwlock) <= 0);
257 osi_Assert(OSI_GET_LOCKID() == avc->vc_rwlockid);
259 ObtainWriteLock(&avc->lock, 118);
260 if (acom & LOCK_UN) {
265 /* If the lock is held exclusive, then only the owning process
266 * or a child can unlock it. Use pid and ppid because they are
267 * unique identifiers.
269 if ((avc->flockCount < 0) && (getpid() != avc->ownslock)) {
271 if (onlymine || (getppid() != avc->ownslock)) {
273 if (onlymine || (u.u_procp->p_ppid != avc->ownslock)) {
275 ReleaseWriteLock(&avc->lock);
280 if (lockIdcmp2(&flock, avc, NULL, onlymine, clid)) {
281 ReleaseWriteLock(&avc->lock);
287 if (avc->flockCount == 0) {
288 ReleaseWriteLock(&avc->lock);
292 /* unlock the lock */
293 if (avc->flockCount > 0) {
295 for (slp = *slpp; slp;) {
296 if (!lockIdcmp2(&flock, avc, slp, onlymine, clid)) {
298 tlp = *slpp = slp->next;
299 osi_FreeSmallSpace(slp);
306 } else if (avc->flockCount == -1) {
307 afs_StoreAllSegments(avc, areq, AFS_ASYNC); /* fsync file early */
309 /* And remove the (only) exclusive lock entry from the list... */
310 osi_FreeSmallSpace(avc->slocks);
313 if (avc->flockCount == 0) {
314 if (!AFS_IS_DISCONNECTED) {
316 tc = afs_Conn(&avc->f.fid, areq, SHARED_LOCK);
318 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_RELEASELOCK);
320 code = RXAFS_ReleaseLock(tc->id, (struct AFSFid *)
321 &avc->f.fid.Fid, &tsync);
327 (tc, code, &avc->f.fid, areq,
328 AFS_STATS_FS_RPCIDX_RELEASELOCK, SHARED_LOCK, NULL));
330 /*printf("Network is dooooooowwwwwwwnnnnnnn\n");*/
335 while (1) { /* set a new lock */
337 * Upgrading from shared locks to Exclusive and vice versa
338 * is a bit tricky and we don't really support it yet. But
339 * we try to support the common used one which is upgrade
340 * a shared lock to an exclusive for the same process...
342 if ((avc->flockCount > 0 && (acom & LOCK_EX))
343 || (avc->flockCount == -1 && (acom & LOCK_SH))) {
345 * Upgrading from shared locks to an exclusive one:
346 * For now if all the shared locks belong to the
347 * same process then we unlock them on the server
348 * and proceed with the upgrade. Unless we change the
349 * server's locking interface impl we prohibit from
350 * unlocking other processes's shared locks...
351 * Upgrading from an exclusive lock to a shared one:
352 * Again only allowed to be done by the same process.
355 for (slp = *slpp; slp;) {
357 (&flock, avc, slp, 1 /*!onlymine */ , clid)) {
362 tlp = *slpp = slp->next;
363 osi_FreeSmallSpace(slp);
371 if (!code && avc->flockCount == 0) {
372 if (!AFS_IS_DISCONNECTED) {
374 tc = afs_Conn(&avc->f.fid, areq, SHARED_LOCK);
377 (AFS_STATS_FS_RPCIDX_RELEASELOCK);
380 RXAFS_ReleaseLock(tc->id,
381 (struct AFSFid *)&avc->
388 (tc, code, &avc->f.fid, areq,
389 AFS_STATS_FS_RPCIDX_RELEASELOCK, SHARED_LOCK,
393 } else if (avc->flockCount == -1 && (acom & LOCK_EX)) {
394 if (lockIdcmp2(&flock, avc, NULL, 1, clid)) {
400 /* compatible here, decide if needs to go to file server. If
401 * we've already got the file locked (and thus read-locked, since
402 * we've already checked for compatibility), we shouldn't send
403 * the call through to the server again */
404 if (avc->flockCount == 0) {
405 /* we're the first on our block, send the call through */
406 lockType = ((acom & LOCK_EX) ? LockWrite : LockRead);
407 if (!AFS_IS_DISCONNECTED) {
409 tc = afs_Conn(&avc->f.fid, areq, SHARED_LOCK);
411 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETLOCK);
413 code = RXAFS_SetLock(tc->id, (struct AFSFid *)
414 &avc->f.fid.Fid, lockType,
421 (tc, code, &avc->f.fid, areq,
422 AFS_STATS_FS_RPCIDX_SETLOCK, SHARED_LOCK,
425 /* XXX - Should probably try and log this when we're
426 * XXX - running with logging enabled. But it's horrid
428 code = 0; /* pretend we worked - ick!!! */
430 code = 0; /* otherwise, pretend things worked */
433 slp = (struct SimpleLocks *)
434 osi_AllocSmallSpace(sizeof(struct SimpleLocks));
435 if (acom & LOCK_EX) {
440 /* Record unique id of process owning exclusive lock. */
441 avc->ownslock = getpid();
444 slp->type = LockWrite;
447 avc->flockCount = -1;
449 slp->type = LockRead;
450 slp->next = avc->slocks;
455 lockIdSet(&flock, slp, clid);
458 /* now, if we got EWOULDBLOCK, and we're supposed to wait, we do */
459 if (((code == EWOULDBLOCK) || (code == EAGAIN) ||
460 (code == UAEWOULDBLOCK) || (code == UAEAGAIN))
461 && !(acom & LOCK_NB)) {
462 /* sleep for a second, allowing interrupts */
463 ReleaseWriteLock(&avc->lock);
464 #if defined(AFS_SGI_ENV)
465 AFS_RWUNLOCK((vnode_t *) avc, VRWLOCK_WRITE);
467 code = afs_osi_Wait(1000, NULL, 1);
468 #if defined(AFS_SGI_ENV)
469 AFS_RWLOCK((vnode_t *) avc, VRWLOCK_WRITE);
471 ObtainWriteLock(&avc->lock, 120);
473 code = EINTR; /* return this if ^C typed */
480 ReleaseWriteLock(&avc->lock);
481 code = afs_CheckCode(code, areq, 1); /* defeat a buggy AIX optimization */
486 /* warn a user that a lock has been ignored */
487 afs_int32 lastWarnTime = 0; /* this is used elsewhere */
491 register afs_int32 now;
494 AFS_STATCNT(DoLockWarning);
495 /* check if we've already warned someone recently */
496 if (now < lastWarnTime + 120)
499 /* otherwise, it is time to nag the user */
501 #ifdef AFS_LINUX26_ENV
503 ("afs: byte-range locks only enforced for processes on this machine.\n");
506 ("afs: byte-range lock/unlock ignored; make sure no one else is running this program.\n");
512 int afs_lockctl(struct vcache * avc, struct eflock * af, int flag,
513 afs_ucred_t * acred, pid_t clid, off_t offset)
514 #elif defined(AFS_SGI_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
515 int afs_lockctl(struct vcache * avc, struct AFS_FLOCK * af, int acmd,
516 afs_ucred_t * acred, pid_t clid)
519 int afs_lockctl(struct vcache * avc, struct AFS_FLOCK * af, int acmd,
523 struct vrequest treq;
528 struct afs_fakestat_state fakestate;
530 AFS_STATCNT(afs_lockctl);
531 if ((code = afs_InitReq(&treq, acred)))
533 afs_InitFakeStat(&fakestate);
537 code = afs_EvalFakeStat(&avc, &fakestate, &treq);
542 if (flag & VNOFLCK) {
546 if (flag & CLNFLCK) {
548 } else if ((flag & GETFLCK) || (flag & RGETFLCK)) {
550 } else if ((flag & SETFLCK) || (flag & RSETFLCK)) {
554 #if (defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)) && !defined(AFS_SUN58_ENV)
555 if ((acmd == F_GETLK) || (acmd == F_RGETLK)) {
557 if (acmd == F_GETLK) {
559 if (af->l_type == F_UNLCK) {
563 #ifndef AFS_OSF_ENV /* getlock is a no-op for osf (for now) */
564 code = HandleGetLock(avc, af, &treq, clid);
566 code = afs_CheckCode(code, &treq, 2); /* defeat buggy AIX optimz */
568 } else if ((acmd == F_SETLK) || (acmd == F_SETLKW)
569 #if (defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)) && !defined(AFS_SUN58_ENV)
570 || (acmd == F_RSETLK) || (acmd == F_RSETLKW)) {
574 /* this next check is safer when left out, but more applications work
575 * with it in. However, they fail in race conditions. The question is
576 * what to do for people who don't have source to their application;
577 * this way at least, they can get work done */
578 #ifdef AFS_LINUX24_ENV
579 if (af->l_len == OFFSET_MAX)
580 af->l_len = 0; /* since some systems indicate it as EOF */
582 if (af->l_len == 0x7fffffff)
583 af->l_len = 0; /* since some systems indicate it as EOF */
584 #ifdef AFS_LINUX_64BIT_KERNEL
585 if (af->l_len == LONG_MAX)
586 af->l_len = 0; /* since some systems indicate it as EOF */
589 /* Java VMs ask for l_len=(long)-1 regardless of OS/CPU; bottom 32 bits
590 * sometimes get masked off by OS */
591 if ((sizeof(af->l_len) == 8) && (af->l_len == 0x7ffffffffffffffeLL))
593 /* next line makes byte range locks always succeed,
594 * even when they should block */
595 if (af->l_whence != 0 || af->l_start != 0 || af->l_len != 0) {
600 /* otherwise we can turn this into a whole-file flock */
601 if (af->l_type == F_RDLCK)
603 else if (af->l_type == F_WRLCK)
605 else if (af->l_type == F_UNLCK)
608 afs_PutFakeStat(&fakestate);
609 return EINVAL; /* unknown lock type */
611 if (((acmd == F_SETLK)
612 #if (defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)) && !defined(AFS_SUN58_ENV)
613 || (acmd == F_RSETLK)
615 ) && code != LOCK_UN)
616 code |= LOCK_NB; /* non-blocking, s.v.p. */
617 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV)
618 code = HandleFlock(avc, code, &treq, clid, 0 /*!onlymine */ );
619 #elif defined(AFS_SGI_ENV)
620 AFS_RWLOCK((vnode_t *) avc, VRWLOCK_WRITE);
621 code = HandleFlock(avc, code, &treq, clid, 0 /*!onlymine */ );
622 AFS_RWUNLOCK((vnode_t *) avc, VRWLOCK_WRITE);
624 code = HandleFlock(avc, code, &treq, 0, 0 /*!onlymine */ );
626 code = afs_CheckCode(code, &treq, 3); /* defeat AIX -O bug */
631 afs_PutFakeStat(&fakestate);
638 * Get a description of the first lock which would
639 * block the lock specified. If the specified lock
640 * would succeed, fill in the lock structure with 'F_UNLCK'.
642 * To do that, we have to ask the server for the lock
644 * 1. The file is not locked by this machine.
645 * 2. Asking for write lock, and only the current
646 * PID has the file read locked.
648 #ifndef AFS_OSF_ENV /* getlock is a no-op for osf (for now) */
650 HandleGetLock(register struct vcache *avc, register struct AFS_FLOCK *af,
651 register struct vrequest *areq, int clid)
653 register afs_int32 code;
654 struct AFS_FLOCK flock;
656 lockIdSet(&flock, NULL, clid);
658 ObtainWriteLock(&avc->lock, 122);
659 if (avc->flockCount == 0) {
661 * We don't know ourselves, so ask the server. Unfortunately, we
662 * don't know the pid. Not even the server knows the pid. Besides,
663 * the process with the lock is on another machine
665 code = GetFlockCount(avc, areq);
666 if (code == 0 || (af->l_type == F_RDLCK && code > 0)) {
667 af->l_type = F_UNLCK;
671 af->l_type = F_RDLCK;
673 af->l_type = F_WRLCK;
676 #if defined(AFS_HAVE_FLOCK_SYSID)
682 if (af->l_type == F_RDLCK) {
684 * We want a read lock. If there are only
685 * read locks, or we are the one with the
686 * write lock, say it is unlocked.
688 if (avc->flockCount > 0 || /* only read locks */
689 !lockIdcmp2(&flock, avc, NULL, 1, clid)) {
690 af->l_type = F_UNLCK;
694 /* one write lock, but who? */
695 af->l_type = F_WRLCK; /* not us, so lock would block */
696 if (avc->slocks) { /* we know who, so tell */
697 af->l_pid = avc->slocks->pid;
698 #if defined(AFS_HAVE_FLOCK_SYSID)
699 af->l_sysid = avc->slocks->sysid;
702 af->l_pid = 0; /* XXX can't happen?? */
703 #if defined(AFS_HAVE_FLOCK_SYSID)
711 * Ok, we want a write lock. If there is a write lock
712 * already, and it is not this process, we fail.
714 if (avc->flockCount < 0) {
715 if (lockIdcmp2(&flock, avc, NULL, 1, clid)) {
716 af->l_type = F_WRLCK;
718 af->l_pid = avc->slocks->pid;
719 #if defined(AFS_HAVE_FLOCK_SYSID)
720 af->l_sysid = avc->slocks->sysid;
723 af->l_pid = 0; /* XXX can't happen?? */
724 #if defined(AFS_HAVE_FLOCK_SYSID)
730 /* we are the one with the write lock */
731 af->l_type = F_UNLCK;
736 * Want a write lock, and we know there are read locks.
737 * If there is more than one, or it isn't us, we cannot lock.
739 if ((avc->flockCount > 1)
740 || lockIdcmp2(&flock, avc, NULL, 1, clid)) {
741 struct SimpleLocks *slp;
743 af->l_type = F_RDLCK;
745 #if defined(AFS_HAVE_FLOCK_SYSID)
748 /* find a pid that isn't our own */
749 for (slp = avc->slocks; slp; slp = slp->next) {
750 if (lockIdcmp2(&flock, NULL, slp, 1, clid)) {
751 af->l_pid = slp->pid;
752 #if defined(AFS_HAVE_FLOCK_SYSID)
753 af->l_sysid = avc->slocks->sysid;
762 * Ok, we want a write lock. If there is a write lock
763 * already, and it is not this process, we fail.
765 if (avc->flockCount < 0) {
766 if (lockIdcmp2(&flock, avc, NULL, 1, clid)) {
767 af->l_type = F_WRLCK;
769 af->l_pid = avc->slocks->pid;
770 #if defined(AFS_HAVE_FLOCK_SYSID)
771 af->l_sysid = avc->slocks->sysid;
774 af->l_pid = 0; /* XXX can't happen?? */
775 #if defined(AFS_HAVE_FLOCK_SYSID)
781 /* we are the one with the write lock */
782 af->l_type = F_UNLCK;
787 * Want a write lock, and we know there are read locks.
788 * If there is more than one, or it isn't us, we cannot lock.
790 if ((avc->flockCount > 1)
791 || lockIdcmp2(&flock, avc, NULL, 1, clid)) {
792 struct SimpleLocks *slp;
793 af->l_type = F_RDLCK;
795 #if defined(AFS_HAVE_FLOCK_SYSID)
798 /* find a pid that isn't our own */
799 for (slp = avc->slocks; slp; slp = slp->next) {
800 if (lockIdcmp2(&flock, NULL, slp, 1, clid)) {
801 af->l_pid = slp->pid;
802 #if defined(AFS_HAVE_FLOCK_SYSID)
803 af->l_sysid = avc->slocks->sysid;
812 * Want a write lock, and there is just one read lock, and it
813 * is this process with a read lock. Ask the server if there
814 * are any more processes with the file locked.
816 code = GetFlockCount(avc, areq);
817 if (code == 0 || code == 1) {
818 af->l_type = F_UNLCK;
822 af->l_type = F_RDLCK;
824 af->l_type = F_WRLCK;
826 #if defined(AFS_HAVE_FLOCK_SYSID)
833 af->l_len = 0; /* to end of file */
836 ReleaseWriteLock(&avc->lock);
840 /* Get the 'flock' count from the server. This comes back in a 'spare'
841 * field from a GetStatus RPC. If we have any problems with the RPC,
842 * we lie and say the file is unlocked. If we ask any 'old' fileservers,
843 * the spare field will be a zero, saying the file is unlocked. This is
844 * OK, as a further 'lock' request will do the right thing.
847 GetFlockCount(struct vcache *avc, struct vrequest *areq)
849 register struct afs_conn *tc;
850 register afs_int32 code;
851 struct AFSFetchStatus OutStatus;
852 struct AFSCallBack CallBack;
853 struct AFSVolSync tsync;
856 temp = areq->flags & O_NONBLOCK;
857 areq->flags |= O_NONBLOCK;
859 /* If we're disconnected, lie and say that we've got no locks. Ick */
860 if (AFS_IS_DISCONNECTED)
864 tc = afs_Conn(&avc->f.fid, areq, SHARED_LOCK);
866 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHSTATUS);
869 RXAFS_FetchStatus(tc->id, (struct AFSFid *)&avc->f.fid.Fid,
870 &OutStatus, &CallBack, &tsync);
876 (tc, code, &avc->f.fid, areq, AFS_STATS_FS_RPCIDX_FETCHSTATUS,
880 areq->flags &= ~O_NONBLOCK;
883 return (0); /* failed, say it is 'unlocked' */
885 return ((int)OutStatus.lockCount);
891 #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)
892 /* Flock not support on System V systems */
894 extern struct fileops afs_fileops;
897 afs_xflock(afs_proc_t *p, void *args, int *retval)
898 #else /* AFS_OSF_ENV */
909 struct vrequest treq;
912 struct afs_fakestat_state fakestate;
914 afs_InitFakeStat(&fakestate);
915 AFS_STATCNT(afs_xflock);
918 uap = (struct a *)args;
919 getf(&fd, uap->fd, FILE_FLAGS_NULL, &u.u_file_state);
920 #else /* AFS_OSF_ENV */
921 uap = (struct a *)u.u_ap;
925 afs_PutFakeStat(&fakestate);
929 if (flockDone = afs_InitReq(&treq, u.u_cred)) {
930 afs_PutFakeStat(&fakestate);
936 /* first determine whether this is any sort of vnode */
937 if (fd->f_type == DTYPE_VNODE) {
938 /* good, this is a vnode; next see if it is an AFS vnode */
939 tvc = VTOAFS(fd->f_data); /* valid, given a vnode */
940 if (IsAfsVnode(AFSTOV(tvc))) {
941 /* This is an AFS vnode, so do the work */
942 code = afs_EvalFakeStat(&tvc, &fakestate, &treq);
945 afs_PutFakeStat(&fakestate);
948 if ((fd->f_flag & (FEXLOCK | FSHLOCK)) && !(uap->com & LOCK_UN)) {
949 /* First, if fd already has lock, release it for relock path */
950 #if defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV)
951 HandleFlock(tvc, LOCK_UN, &treq, u.u_procp->p_pid,
954 HandleFlock(tvc, LOCK_UN, &treq, 0, 0 /*!onlymine */ );
956 fd->f_flag &= ~(FEXLOCK | FSHLOCK);
958 /* now try the requested operation */
960 #if defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV)
962 HandleFlock(tvc, uap->com, &treq, u.u_procp->p_pid,
965 code = HandleFlock(tvc, uap->com, &treq, 0, 0 /*!onlymine */ );
971 if (uap->com & LOCK_UN) {
973 fd->f_flag &= ~(FEXLOCK | FSHLOCK);
977 #else /* AFS_OSF_ENV */
980 if (uap->com & LOCK_SH)
981 fd->f_flag |= FSHLOCK;
982 else if (uap->com & LOCK_EX)
983 fd->f_flag |= FEXLOCK;
987 fd->f_ops = &afs_fileops;
992 code = flock(p, args, retval);
999 afs_PutFakeStat(&fakestate);
1001 #else /* AFS_OSF_ENV */
1004 AFS_DISCON_UNLOCK();
1005 afs_PutFakeStat(&fakestate);
1009 #endif /* !defined(AFS_AIX_ENV) && !defined(AFS_HPUX_ENV) && !defined(AFS_SUN5_ENV) && !defined(UKERNEL) && !defined(AFS_LINUX20_ENV) */