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 lockIdSet(struct AFS_FLOCK *flock, struct SimpleLocks *slp, int clid)
45 #if defined(AFS_SUN5_ENV)
46 register proc_t *procp = ttoproc(curthread);
48 #if !defined(AFS_AIX41_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_SGI65_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_XBSD_ENV)
50 struct proc *procp = OSI_GET_CURRENT_PROCP();
52 struct proc *procp = u.u_procp;
53 #endif /* AFS_SGI_ENV */
56 #if defined(AFS_SGI65_ENV)
58 get_current_flid(&flid);
67 slp->sysid = u.u_sysid;
71 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV)
74 slp->pid = procp->p_pid;
76 slp->sysid = procp->p_sysid;
77 slp->pid = procp->p_epid;
80 #if defined(AFS_SGI_ENV)
82 slp->sysid = flid.fl_sysid;
84 slp->sysid = OSI_GET_CURRENT_SYSID();
88 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
91 #if defined(AFS_LINUX20_ENV) || defined(AFS_HPUX_ENV)
94 slp->pid = u.u_procp->p_pid;
97 #endif /* AFS_AIX_ENV */
98 #endif /* AFS_AIX32_ENV */
101 #if defined(AFS_AIX32_ENV)
104 flock->l_pid = getpid();
106 flock->l_sysid = u.u_sysid;
107 flock->l_pid = u.u_epid;
110 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV)
113 flock->l_pid = procp->p_pid;
115 flock->l_sysid = procp->p_sysid;
116 flock->l_pid = procp->p_epid;
119 #if defined(AFS_SGI_ENV)
121 flock->l_sysid = flid.fl_sysid;
123 flock->l_sysid = OSI_GET_CURRENT_SYSID();
127 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
130 #if defined(AFS_LINUX20_ENV) || defined(AFS_HPUX_ENV)
131 flock->l_pid = getpid();
133 flock->l_pid = u.u_procp->p_pid;
137 #endif /* AFS_AIX_ENV */
138 #endif /* AFS_AIX32_ENV */
142 /* return 1 (true) if specified flock does not match alp (if
143 * specified), or any of the slp structs (if alp == 0)
145 /* I'm not sure that the comparsion of flock->pid to p_ppid
146 * is correct. Should that be a comparision of alp (or slp) ->pid
147 * to p_ppid? Especially in the context of the lower loop, where
148 * the repeated comparison doesn't make much sense...
150 /* onlymine - don't match any locks which are held by my parent */
151 /* clid - only irix 6.5 */
154 lockIdcmp2(struct AFS_FLOCK *flock1, struct vcache *vp,
155 register struct SimpleLocks *alp, int onlymine, int clid)
157 register struct SimpleLocks *slp;
158 #if defined(AFS_SUN5_ENV)
159 register proc_t *procp = ttoproc(curthread);
161 #if !defined(AFS_AIX41_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_SGI65_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_XBSD_ENV)
163 struct proc *procp = curprocp;
164 #else /* AFS_SGI64_ENV */
165 struct proc *procp = u.u_procp;
166 #endif /* AFS_SGI64_ENV */
171 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
172 if (flock1->l_sysid != alp->sysid) {
176 if ((flock1->l_pid == alp->pid) ||
177 #if defined(AFS_AIX41_ENV) || defined(AFS_LINUX20_ENV) || defined(AFS_HPUX_ENV)
178 (!onlymine && (flock1->l_pid == getppid()))
180 #if defined(AFS_SGI65_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
181 /* XXX check this. used to be *only* irix for some reason. */
182 (!onlymine && (flock1->l_pid == clid))
184 (!onlymine && (flock1->l_pid == procp->p_ppid))
193 for (slp = vp->slocks; slp; slp = slp->next) {
194 #if defined(AFS_HAVE_FLOCK_SYSID)
195 if (flock1->l_sysid != slp->sysid) {
199 if (flock1->l_pid == slp->pid) {
203 return (1); /* failure */
207 /* we don't send multiple read flocks to the server, but rather just count
208 them up ourselves. Of course, multiple write locks are incompatible.
210 Note that we should always try to release a lock, even if we have
211 a network problem sending the release command through, since often
212 a lock is released on a close call, when the user can't retry anyway.
214 After we remove it from our structure, the lock will no longer be
215 kept alive, and the server should time it out within a few minutes.
217 94.04.13 add "force" parameter. If a child explicitly unlocks a
218 file, I guess we'll permit it. however, we don't want simple,
219 innocent closes by children to unlock files in the parent process.
221 If called when disconnected support is unabled, the discon_lock must
224 /* clid - nonzero on sgi sunos osf1 only */
226 HandleFlock(register struct vcache *avc, int acom, struct vrequest *areq,
227 pid_t clid, int onlymine)
230 struct SimpleLocks *slp, *tlp, **slpp;
232 struct AFSVolSync tsync;
234 struct AFS_FLOCK flock;
236 AFS_STATCNT(HandleFlock);
237 code = 0; /* default when we don't make any network calls */
238 lockIdSet(&flock, NULL, clid);
240 #if defined(AFS_SGI_ENV)
241 osi_Assert(valusema(&avc->vc_rwlock) <= 0);
242 osi_Assert(OSI_GET_LOCKID() == avc->vc_rwlockid);
244 ObtainWriteLock(&avc->lock, 118);
245 if (acom & LOCK_UN) {
250 /* If the lock is held exclusive, then only the owning process
251 * or a child can unlock it. Use pid and ppid because they are
252 * unique identifiers.
254 if ((avc->flockCount < 0) && (getpid() != avc->ownslock)) {
256 if (onlymine || (getppid() != avc->ownslock)) {
258 if (onlymine || (u.u_procp->p_ppid != avc->ownslock)) {
260 ReleaseWriteLock(&avc->lock);
265 if (lockIdcmp2(&flock, avc, NULL, onlymine, clid)) {
266 ReleaseWriteLock(&avc->lock);
272 if (avc->flockCount == 0) {
273 ReleaseWriteLock(&avc->lock);
277 /* unlock the lock */
278 if (avc->flockCount > 0) {
280 for (slp = *slpp; slp;) {
281 if (!lockIdcmp2(&flock, avc, slp, onlymine, clid)) {
283 tlp = *slpp = slp->next;
284 osi_FreeSmallSpace(slp);
291 } else if (avc->flockCount == -1) {
292 afs_StoreAllSegments(avc, areq, AFS_ASYNC); /* fsync file early */
294 /* And remove the (only) exclusive lock entry from the list... */
295 osi_FreeSmallSpace(avc->slocks);
298 if (avc->flockCount == 0) {
299 if (!AFS_IS_DISCONNECTED) {
301 tc = afs_Conn(&avc->f.fid, areq, SHARED_LOCK);
303 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_RELEASELOCK);
305 code = RXAFS_ReleaseLock(tc->id, (struct AFSFid *)
306 &avc->f.fid.Fid, &tsync);
312 (tc, code, &avc->f.fid, areq,
313 AFS_STATS_FS_RPCIDX_RELEASELOCK, SHARED_LOCK, NULL));
315 /*printf("Network is dooooooowwwwwwwnnnnnnn\n");*/
320 while (1) { /* set a new lock */
322 * Upgrading from shared locks to Exclusive and vice versa
323 * is a bit tricky and we don't really support it yet. But
324 * we try to support the common used one which is upgrade
325 * a shared lock to an exclusive for the same process...
327 if ((avc->flockCount > 0 && (acom & LOCK_EX))
328 || (avc->flockCount == -1 && (acom & LOCK_SH))) {
330 * Upgrading from shared locks to an exclusive one:
331 * For now if all the shared locks belong to the
332 * same process then we unlock them on the server
333 * and proceed with the upgrade. Unless we change the
334 * server's locking interface impl we prohibit from
335 * unlocking other processes's shared locks...
336 * Upgrading from an exclusive lock to a shared one:
337 * Again only allowed to be done by the same process.
340 for (slp = *slpp; slp;) {
342 (&flock, avc, slp, 1 /*!onlymine */ , clid)) {
347 tlp = *slpp = slp->next;
348 osi_FreeSmallSpace(slp);
356 if (!code && avc->flockCount == 0) {
357 if (!AFS_IS_DISCONNECTED) {
359 tc = afs_Conn(&avc->f.fid, areq, SHARED_LOCK);
362 (AFS_STATS_FS_RPCIDX_RELEASELOCK);
365 RXAFS_ReleaseLock(tc->id,
366 (struct AFSFid *)&avc->
373 (tc, code, &avc->f.fid, areq,
374 AFS_STATS_FS_RPCIDX_RELEASELOCK, SHARED_LOCK,
378 } else if (avc->flockCount == -1 && (acom & LOCK_EX)) {
379 if (lockIdcmp2(&flock, avc, NULL, 1, clid)) {
385 /* compatible here, decide if needs to go to file server. If
386 * we've already got the file locked (and thus read-locked, since
387 * we've already checked for compatibility), we shouldn't send
388 * the call through to the server again */
389 if (avc->flockCount == 0) {
390 /* we're the first on our block, send the call through */
391 lockType = ((acom & LOCK_EX) ? LockWrite : LockRead);
392 if (!AFS_IS_DISCONNECTED) {
394 tc = afs_Conn(&avc->f.fid, areq, SHARED_LOCK);
396 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETLOCK);
398 code = RXAFS_SetLock(tc->id, (struct AFSFid *)
399 &avc->f.fid.Fid, lockType,
406 (tc, code, &avc->f.fid, areq,
407 AFS_STATS_FS_RPCIDX_SETLOCK, SHARED_LOCK,
410 /* XXX - Should probably try and log this when we're
411 * XXX - running with logging enabled. But it's horrid
413 code = 0; /* pretend we worked - ick!!! */
415 code = 0; /* otherwise, pretend things worked */
418 slp = (struct SimpleLocks *)
419 osi_AllocSmallSpace(sizeof(struct SimpleLocks));
420 if (acom & LOCK_EX) {
425 /* Record unique id of process owning exclusive lock. */
426 avc->ownslock = getpid();
429 slp->type = LockWrite;
432 avc->flockCount = -1;
434 slp->type = LockRead;
435 slp->next = avc->slocks;
440 lockIdSet(&flock, slp, clid);
443 /* now, if we got EWOULDBLOCK, and we're supposed to wait, we do */
444 if (((code == EWOULDBLOCK) || (code == EAGAIN) ||
445 (code == UAEWOULDBLOCK) || (code == UAEAGAIN))
446 && !(acom & LOCK_NB)) {
447 /* sleep for a second, allowing interrupts */
448 ReleaseWriteLock(&avc->lock);
449 #if defined(AFS_SGI_ENV)
450 AFS_RWUNLOCK((vnode_t *) avc, VRWLOCK_WRITE);
452 code = afs_osi_Wait(1000, NULL, 1);
453 #if defined(AFS_SGI_ENV)
454 AFS_RWLOCK((vnode_t *) avc, VRWLOCK_WRITE);
456 ObtainWriteLock(&avc->lock, 120);
458 code = EINTR; /* return this if ^C typed */
465 ReleaseWriteLock(&avc->lock);
466 code = afs_CheckCode(code, areq, 1); /* defeat a buggy AIX optimization */
471 /* warn a user that a lock has been ignored */
472 afs_int32 lastWarnTime = 0; /* this is used elsewhere */
476 register afs_int32 now;
479 AFS_STATCNT(DoLockWarning);
480 /* check if we've already warned someone recently */
481 if (now < lastWarnTime + 120)
484 /* otherwise, it is time to nag the user */
486 #ifdef AFS_LINUX26_ENV
488 ("afs: byte-range locks only enforced for processes on this machine.\n");
491 ("afs: byte-range lock/unlock ignored; make sure no one else is running this program.\n");
497 int afs_lockctl(struct vcache * avc, struct eflock * af, int flag,
498 struct AFS_UCRED * acred, pid_t clid, off_t offset)
499 #elif defined(AFS_SGI_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
500 int afs_lockctl(struct vcache * avc, struct AFS_FLOCK * af, int acmd,
501 struct AFS_UCRED * acred, pid_t clid)
504 int afs_lockctl(struct vcache * avc, struct AFS_FLOCK * af, int acmd,
505 struct AFS_UCRED * acred)
508 struct vrequest treq;
513 struct afs_fakestat_state fakestate;
515 AFS_STATCNT(afs_lockctl);
516 if ((code = afs_InitReq(&treq, acred)))
518 afs_InitFakeStat(&fakestate);
522 code = afs_EvalFakeStat(&avc, &fakestate, &treq);
527 if (flag & VNOFLCK) {
531 if (flag & CLNFLCK) {
533 } else if ((flag & GETFLCK) || (flag & RGETFLCK)) {
535 } else if ((flag & SETFLCK) || (flag & RSETFLCK)) {
539 #if (defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)) && !defined(AFS_SUN58_ENV)
540 if ((acmd == F_GETLK) || (acmd == F_RGETLK)) {
542 if (acmd == F_GETLK) {
544 if (af->l_type == F_UNLCK) {
548 #ifndef AFS_OSF_ENV /* getlock is a no-op for osf (for now) */
549 code = HandleGetLock(avc, af, &treq, clid);
551 code = afs_CheckCode(code, &treq, 2); /* defeat buggy AIX optimz */
553 } else if ((acmd == F_SETLK) || (acmd == F_SETLKW)
554 #if (defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)) && !defined(AFS_SUN58_ENV)
555 || (acmd == F_RSETLK) || (acmd == F_RSETLKW)) {
559 /* this next check is safer when left out, but more applications work
560 * with it in. However, they fail in race conditions. The question is
561 * what to do for people who don't have source to their application;
562 * this way at least, they can get work done */
563 #ifdef AFS_LINUX24_ENV
564 if (af->l_len == OFFSET_MAX)
565 af->l_len = 0; /* since some systems indicate it as EOF */
567 if (af->l_len == 0x7fffffff)
568 af->l_len = 0; /* since some systems indicate it as EOF */
569 #ifdef AFS_LINUX_64BIT_KERNEL
570 if (af->l_len == LONG_MAX)
571 af->l_len = 0; /* since some systems indicate it as EOF */
574 /* Java VMs ask for l_len=(long)-1 regardless of OS/CPU; bottom 32 bits
575 * sometimes get masked off by OS */
576 if ((sizeof(af->l_len) == 8) && (af->l_len == 0x7ffffffffffffffeLL))
578 /* next line makes byte range locks always succeed,
579 * even when they should block */
580 if (af->l_whence != 0 || af->l_start != 0 || af->l_len != 0) {
585 /* otherwise we can turn this into a whole-file flock */
586 if (af->l_type == F_RDLCK)
588 else if (af->l_type == F_WRLCK)
590 else if (af->l_type == F_UNLCK)
593 afs_PutFakeStat(&fakestate);
594 return EINVAL; /* unknown lock type */
596 if (((acmd == F_SETLK)
597 #if (defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)) && !defined(AFS_SUN58_ENV)
598 || (acmd == F_RSETLK)
600 ) && code != LOCK_UN)
601 code |= LOCK_NB; /* non-blocking, s.v.p. */
602 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV)
603 code = HandleFlock(avc, code, &treq, clid, 0 /*!onlymine */ );
604 #elif defined(AFS_SGI_ENV)
605 AFS_RWLOCK((vnode_t *) avc, VRWLOCK_WRITE);
606 code = HandleFlock(avc, code, &treq, clid, 0 /*!onlymine */ );
607 AFS_RWUNLOCK((vnode_t *) avc, VRWLOCK_WRITE);
609 code = HandleFlock(avc, code, &treq, 0, 0 /*!onlymine */ );
611 code = afs_CheckCode(code, &treq, 3); /* defeat AIX -O bug */
616 afs_PutFakeStat(&fakestate);
623 * Get a description of the first lock which would
624 * block the lock specified. If the specified lock
625 * would succeed, fill in the lock structure with 'F_UNLCK'.
627 * To do that, we have to ask the server for the lock
629 * 1. The file is not locked by this machine.
630 * 2. Asking for write lock, and only the current
631 * PID has the file read locked.
633 #ifndef AFS_OSF_ENV /* getlock is a no-op for osf (for now) */
635 HandleGetLock(register struct vcache *avc, register struct AFS_FLOCK *af,
636 register struct vrequest *areq, int clid)
638 register afs_int32 code;
639 struct AFS_FLOCK flock;
641 lockIdSet(&flock, NULL, clid);
643 ObtainWriteLock(&avc->lock, 122);
644 if (avc->flockCount == 0) {
646 * We don't know ourselves, so ask the server. Unfortunately, we
647 * don't know the pid. Not even the server knows the pid. Besides,
648 * the process with the lock is on another machine
650 code = GetFlockCount(avc, areq);
651 if (code == 0 || (af->l_type == F_RDLCK && code > 0)) {
652 af->l_type = F_UNLCK;
656 af->l_type = F_RDLCK;
658 af->l_type = F_WRLCK;
661 #if defined(AFS_HAVE_FLOCK_SYSID)
667 if (af->l_type == F_RDLCK) {
669 * We want a read lock. If there are only
670 * read locks, or we are the one with the
671 * write lock, say it is unlocked.
673 if (avc->flockCount > 0 || /* only read locks */
674 !lockIdcmp2(&flock, avc, NULL, 1, clid)) {
675 af->l_type = F_UNLCK;
679 /* one write lock, but who? */
680 af->l_type = F_WRLCK; /* not us, so lock would block */
681 if (avc->slocks) { /* we know who, so tell */
682 af->l_pid = avc->slocks->pid;
683 #if defined(AFS_HAVE_FLOCK_SYSID)
684 af->l_sysid = avc->slocks->sysid;
687 af->l_pid = 0; /* XXX can't happen?? */
688 #if defined(AFS_HAVE_FLOCK_SYSID)
696 * Ok, we want a write lock. If there is a write lock
697 * already, and it is not this process, we fail.
699 if (avc->flockCount < 0) {
700 if (lockIdcmp2(&flock, avc, NULL, 1, clid)) {
701 af->l_type = F_WRLCK;
703 af->l_pid = avc->slocks->pid;
704 #if defined(AFS_HAVE_FLOCK_SYSID)
705 af->l_sysid = avc->slocks->sysid;
708 af->l_pid = 0; /* XXX can't happen?? */
709 #if defined(AFS_HAVE_FLOCK_SYSID)
715 /* we are the one with the write lock */
716 af->l_type = F_UNLCK;
721 * Want a write lock, and we know there are read locks.
722 * If there is more than one, or it isn't us, we cannot lock.
724 if ((avc->flockCount > 1)
725 || lockIdcmp2(&flock, avc, NULL, 1, clid)) {
726 struct SimpleLocks *slp;
728 af->l_type = F_RDLCK;
730 #if defined(AFS_HAVE_FLOCK_SYSID)
733 /* find a pid that isn't our own */
734 for (slp = avc->slocks; slp; slp = slp->next) {
735 if (lockIdcmp2(&flock, NULL, slp, 1, clid)) {
736 af->l_pid = slp->pid;
737 #if defined(AFS_HAVE_FLOCK_SYSID)
738 af->l_sysid = avc->slocks->sysid;
747 * Ok, we want a write lock. If there is a write lock
748 * already, and it is not this process, we fail.
750 if (avc->flockCount < 0) {
751 if (lockIdcmp2(&flock, avc, NULL, 1, clid)) {
752 af->l_type = F_WRLCK;
754 af->l_pid = avc->slocks->pid;
755 #if defined(AFS_HAVE_FLOCK_SYSID)
756 af->l_sysid = avc->slocks->sysid;
759 af->l_pid = 0; /* XXX can't happen?? */
760 #if defined(AFS_HAVE_FLOCK_SYSID)
766 /* we are the one with the write lock */
767 af->l_type = F_UNLCK;
772 * Want a write lock, and we know there are read locks.
773 * If there is more than one, or it isn't us, we cannot lock.
775 if ((avc->flockCount > 1)
776 || lockIdcmp2(&flock, avc, NULL, 1, clid)) {
777 struct SimpleLocks *slp;
778 af->l_type = F_RDLCK;
780 #if defined(AFS_HAVE_FLOCK_SYSID)
783 /* find a pid that isn't our own */
784 for (slp = avc->slocks; slp; slp = slp->next) {
785 if (lockIdcmp2(&flock, NULL, slp, 1, clid)) {
786 af->l_pid = slp->pid;
787 #if defined(AFS_HAVE_FLOCK_SYSID)
788 af->l_sysid = avc->slocks->sysid;
797 * Want a write lock, and there is just one read lock, and it
798 * is this process with a read lock. Ask the server if there
799 * are any more processes with the file locked.
801 code = GetFlockCount(avc, areq);
802 if (code == 0 || code == 1) {
803 af->l_type = F_UNLCK;
807 af->l_type = F_RDLCK;
809 af->l_type = F_WRLCK;
811 #if defined(AFS_HAVE_FLOCK_SYSID)
818 af->l_len = 0; /* to end of file */
821 ReleaseWriteLock(&avc->lock);
825 /* Get the 'flock' count from the server. This comes back in a 'spare'
826 * field from a GetStatus RPC. If we have any problems with the RPC,
827 * we lie and say the file is unlocked. If we ask any 'old' fileservers,
828 * the spare field will be a zero, saying the file is unlocked. This is
829 * OK, as a further 'lock' request will do the right thing.
832 GetFlockCount(struct vcache *avc, struct vrequest *areq)
834 register struct afs_conn *tc;
835 register afs_int32 code;
836 struct AFSFetchStatus OutStatus;
837 struct AFSCallBack CallBack;
838 struct AFSVolSync tsync;
841 temp = areq->flags & O_NONBLOCK;
842 areq->flags |= O_NONBLOCK;
844 /* If we're disconnected, lie and say that we've got no locks. Ick */
845 if (AFS_IS_DISCONNECTED)
849 tc = afs_Conn(&avc->f.fid, areq, SHARED_LOCK);
851 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHSTATUS);
854 RXAFS_FetchStatus(tc->id, (struct AFSFid *)&avc->f.fid.Fid,
855 &OutStatus, &CallBack, &tsync);
861 (tc, code, &avc->f.fid, areq, AFS_STATS_FS_RPCIDX_FETCHSTATUS,
865 areq->flags &= ~O_NONBLOCK;
868 return (0); /* failed, say it is 'unlocked' */
870 return ((int)OutStatus.lockCount);
876 #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)
877 /* Flock not support on System V systems */
879 extern struct fileops afs_fileops;
882 afs_xflock(struct proc *p, void *args, int *retval)
883 #else /* AFS_OSF_ENV */
894 struct vrequest treq;
897 struct afs_fakestat_state fakestate;
899 afs_InitFakeStat(&fakestate);
900 AFS_STATCNT(afs_xflock);
903 uap = (struct a *)args;
904 getf(&fd, uap->fd, FILE_FLAGS_NULL, &u.u_file_state);
905 #else /* AFS_OSF_ENV */
906 uap = (struct a *)u.u_ap;
910 afs_PutFakeStat(&fakestate);
914 if (flockDone = afs_InitReq(&treq, u.u_cred)) {
915 afs_PutFakeStat(&fakestate);
921 /* first determine whether this is any sort of vnode */
922 if (fd->f_type == DTYPE_VNODE) {
923 /* good, this is a vnode; next see if it is an AFS vnode */
924 tvc = VTOAFS(fd->f_data); /* valid, given a vnode */
925 if (IsAfsVnode(AFSTOV(tvc))) {
926 /* This is an AFS vnode, so do the work */
927 code = afs_EvalFakeStat(&tvc, &fakestate, &treq);
930 afs_PutFakeStat(&fakestate);
933 if ((fd->f_flag & (FEXLOCK | FSHLOCK)) && !(uap->com & LOCK_UN)) {
934 /* First, if fd already has lock, release it for relock path */
935 #if defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV)
936 HandleFlock(tvc, LOCK_UN, &treq, u.u_procp->p_pid,
939 HandleFlock(tvc, LOCK_UN, &treq, 0, 0 /*!onlymine */ );
941 fd->f_flag &= ~(FEXLOCK | FSHLOCK);
943 /* now try the requested operation */
945 #if defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV)
947 HandleFlock(tvc, uap->com, &treq, u.u_procp->p_pid,
950 code = HandleFlock(tvc, uap->com, &treq, 0, 0 /*!onlymine */ );
956 if (uap->com & LOCK_UN) {
958 fd->f_flag &= ~(FEXLOCK | FSHLOCK);
962 #else /* AFS_OSF_ENV */
965 if (uap->com & LOCK_SH)
966 fd->f_flag |= FSHLOCK;
967 else if (uap->com & LOCK_EX)
968 fd->f_flag |= FEXLOCK;
972 fd->f_ops = &afs_fileops;
977 code = flock(p, args, retval);
984 afs_PutFakeStat(&fakestate);
986 #else /* AFS_OSF_ENV */
990 afs_PutFakeStat(&fakestate);
994 #endif /* !defined(AFS_AIX_ENV) && !defined(AFS_HPUX_ENV) && !defined(AFS_SUN5_ENV) && !defined(UKERNEL) && !defined(AFS_LINUX20_ENV) */