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"
33 /* Static prototypes */
34 static int HandleGetLock(register struct vcache *avc,
35 register struct AFS_FLOCK *af,
36 register struct vrequest *areq, int clid);
37 static int GetFlockCount(struct vcache *avc, struct vrequest *areq);
38 static int lockIdcmp2(struct AFS_FLOCK *flock1, struct vcache *vp,
39 register struct SimpleLocks *alp, int onlymine,
41 static void DoLockWarning(void);
43 /* int clid; * non-zero on SGI, OSF, SunOS, Darwin, xBSD ** XXX ptr type */
45 lockIdSet(struct AFS_FLOCK *flock, struct SimpleLocks *slp, int clid)
47 #if defined(AFS_SUN5_ENV)
48 register proc_t *procp = ttoproc(curthread);
50 #if !defined(AFS_AIX41_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_SGI65_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_XBSD_ENV)
52 struct proc *procp = OSI_GET_CURRENT_PROCP();
54 struct proc *procp = u.u_procp;
55 #endif /* AFS_SGI_ENV */
58 #if defined(AFS_SGI65_ENV)
60 get_current_flid(&flid);
69 slp->sysid = u.u_sysid;
73 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV)
76 slp->pid = procp->p_pid;
78 slp->sysid = procp->p_sysid;
79 slp->pid = procp->p_epid;
82 #if defined(AFS_SGI_ENV)
84 slp->sysid = flid.fl_sysid;
86 slp->sysid = OSI_GET_CURRENT_SYSID();
90 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
93 #if defined(AFS_LINUX20_ENV) || defined(AFS_HPUX_ENV)
96 slp->pid = u.u_procp->p_pid;
99 #endif /* AFS_AIX_ENV */
100 #endif /* AFS_AIX32_ENV */
103 #if defined(AFS_AIX32_ENV)
106 flock->l_pid = getpid();
108 flock->l_sysid = u.u_sysid;
109 flock->l_pid = u.u_epid;
112 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV)
115 flock->l_pid = procp->p_pid;
117 flock->l_sysid = procp->p_sysid;
118 flock->l_pid = procp->p_epid;
121 #if defined(AFS_SGI_ENV)
123 flock->l_sysid = flid.fl_sysid;
125 flock->l_sysid = OSI_GET_CURRENT_SYSID();
129 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
132 #if defined(AFS_LINUX20_ENV) || defined(AFS_HPUX_ENV)
133 flock->l_pid = getpid();
135 flock->l_pid = u.u_procp->p_pid;
139 #endif /* AFS_AIX_ENV */
140 #endif /* AFS_AIX32_ENV */
144 /* return 1 (true) if specified flock does not match alp (if
145 * specified), or any of the slp structs (if alp == 0)
147 /* I'm not sure that the comparsion of flock->pid to p_ppid
148 * is correct. Should that be a comparision of alp (or slp) ->pid
149 * to p_ppid? Especially in the context of the lower loop, where
150 * the repeated comparison doesn't make much sense...
152 /* onlymine - don't match any locks which are held by my parent */
153 /* clid - only irix 6.5 */
156 lockIdcmp2(struct AFS_FLOCK *flock1, struct vcache *vp,
157 register struct SimpleLocks *alp, int onlymine, int clid)
159 register struct SimpleLocks *slp;
160 #if defined(AFS_SUN5_ENV)
161 register proc_t *procp = ttoproc(curthread);
163 #if !defined(AFS_AIX41_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_SGI65_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_XBSD_ENV)
165 struct proc *procp = curprocp;
166 #else /* AFS_SGI64_ENV */
167 struct proc *procp = u.u_procp;
168 #endif /* AFS_SGI64_ENV */
173 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
174 if (flock1->l_sysid != alp->sysid) {
178 if ((flock1->l_pid == alp->pid) ||
179 #if defined(AFS_AIX41_ENV) || defined(AFS_LINUX20_ENV) || defined(AFS_HPUX_ENV)
180 (!onlymine && (flock1->l_pid == getppid()))
182 #if defined(AFS_SGI65_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
183 /* XXX check this. used to be *only* irix for some reason. */
184 (!onlymine && (flock1->l_pid == clid))
186 (!onlymine && (flock1->l_pid == procp->p_ppid))
195 for (slp = vp->slocks; slp; slp = slp->next) {
196 #if defined(AFS_HAVE_FLOCK_SYSID)
197 if (flock1->l_sysid != slp->sysid) {
201 if (flock1->l_pid == slp->pid) {
205 return (1); /* failure */
209 /* we don't send multiple read flocks to the server, but rather just count
210 them up ourselves. Of course, multiple write locks are incompatible.
212 Note that we should always try to release a lock, even if we have
213 a network problem sending the release command through, since often
214 a lock is released on a close call, when the user can't retry anyway.
216 After we remove it from our structure, the lock will no longer be
217 kept alive, and the server should time it out within a few minutes.
219 94.04.13 add "force" parameter. If a child explicitly unlocks a
220 file, I guess we'll permit it. however, we don't want simple,
221 innocent closes by children to unlock files in the parent process.
223 If called when disconnected support is unabled, the discon_lock must
226 /* clid - nonzero on sgi sunos osf1 only */
228 HandleFlock(register struct vcache *avc, int acom, struct vrequest *areq,
229 pid_t clid, int onlymine)
232 struct SimpleLocks *slp, *tlp, **slpp;
234 struct AFSVolSync tsync;
236 struct AFS_FLOCK flock;
238 AFS_STATCNT(HandleFlock);
239 code = 0; /* default when we don't make any network calls */
240 lockIdSet(&flock, NULL, clid);
242 #if defined(AFS_SGI_ENV)
243 osi_Assert(valusema(&avc->vc_rwlock) <= 0);
244 osi_Assert(OSI_GET_LOCKID() == avc->vc_rwlockid);
246 ObtainWriteLock(&avc->lock, 118);
247 if (acom & LOCK_UN) {
252 /* If the lock is held exclusive, then only the owning process
253 * or a child can unlock it. Use pid and ppid because they are
254 * unique identifiers.
256 if ((avc->flockCount < 0) && (getpid() != avc->ownslock)) {
258 if (onlymine || (getppid() != avc->ownslock)) {
260 if (onlymine || (u.u_procp->p_ppid != avc->ownslock)) {
262 ReleaseWriteLock(&avc->lock);
267 if (lockIdcmp2(&flock, avc, NULL, onlymine, clid)) {
268 ReleaseWriteLock(&avc->lock);
274 if (avc->flockCount == 0) {
275 ReleaseWriteLock(&avc->lock);
279 /* unlock the lock */
280 if (avc->flockCount > 0) {
282 for (slp = *slpp; slp;) {
283 if (!lockIdcmp2(&flock, avc, slp, onlymine, clid)) {
285 tlp = *slpp = slp->next;
286 osi_FreeSmallSpace(slp);
293 } else if (avc->flockCount == -1) {
294 afs_StoreAllSegments(avc, areq, AFS_ASYNC); /* fsync file early */
296 /* And remove the (only) exclusive lock entry from the list... */
297 osi_FreeSmallSpace(avc->slocks);
300 if (avc->flockCount == 0) {
301 if (!AFS_IS_DISCONNECTED) {
303 tc = afs_Conn(&avc->f.fid, areq, SHARED_LOCK);
305 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_RELEASELOCK);
307 code = RXAFS_ReleaseLock(tc->id, (struct AFSFid *)
308 &avc->f.fid.Fid, &tsync);
314 (tc, code, &avc->f.fid, areq,
315 AFS_STATS_FS_RPCIDX_RELEASELOCK, SHARED_LOCK, NULL));
317 /*printf("Network is dooooooowwwwwwwnnnnnnn\n");*/
322 while (1) { /* set a new lock */
324 * Upgrading from shared locks to Exclusive and vice versa
325 * is a bit tricky and we don't really support it yet. But
326 * we try to support the common used one which is upgrade
327 * a shared lock to an exclusive for the same process...
329 if ((avc->flockCount > 0 && (acom & LOCK_EX))
330 || (avc->flockCount == -1 && (acom & LOCK_SH))) {
332 * Upgrading from shared locks to an exclusive one:
333 * For now if all the shared locks belong to the
334 * same process then we unlock them on the server
335 * and proceed with the upgrade. Unless we change the
336 * server's locking interface impl we prohibit from
337 * unlocking other processes's shared locks...
338 * Upgrading from an exclusive lock to a shared one:
339 * Again only allowed to be done by the same process.
342 for (slp = *slpp; slp;) {
344 (&flock, avc, slp, 1 /*!onlymine */ , clid)) {
349 tlp = *slpp = slp->next;
350 osi_FreeSmallSpace(slp);
358 if (!code && avc->flockCount == 0) {
359 if (!AFS_IS_DISCONNECTED) {
361 tc = afs_Conn(&avc->f.fid, areq, SHARED_LOCK);
364 (AFS_STATS_FS_RPCIDX_RELEASELOCK);
367 RXAFS_ReleaseLock(tc->id,
368 (struct AFSFid *)&avc->
375 (tc, code, &avc->f.fid, areq,
376 AFS_STATS_FS_RPCIDX_RELEASELOCK, SHARED_LOCK,
380 } else if (avc->flockCount == -1 && (acom & LOCK_EX)) {
381 if (lockIdcmp2(&flock, avc, NULL, 1, clid)) {
387 /* compatible here, decide if needs to go to file server. If
388 * we've already got the file locked (and thus read-locked, since
389 * we've already checked for compatibility), we shouldn't send
390 * the call through to the server again */
391 if (avc->flockCount == 0) {
392 /* we're the first on our block, send the call through */
393 lockType = ((acom & LOCK_EX) ? LockWrite : LockRead);
394 if (!AFS_IS_DISCONNECTED) {
396 tc = afs_Conn(&avc->f.fid, areq, SHARED_LOCK);
398 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETLOCK);
400 code = RXAFS_SetLock(tc->id, (struct AFSFid *)
401 &avc->f.fid.Fid, lockType,
408 (tc, code, &avc->f.fid, areq,
409 AFS_STATS_FS_RPCIDX_SETLOCK, SHARED_LOCK,
412 /* XXX - Should probably try and log this when we're
413 * XXX - running with logging enabled. But it's horrid
415 code = 0; /* pretend we worked - ick!!! */
417 code = 0; /* otherwise, pretend things worked */
420 slp = (struct SimpleLocks *)
421 osi_AllocSmallSpace(sizeof(struct SimpleLocks));
422 if (acom & LOCK_EX) {
427 /* Record unique id of process owning exclusive lock. */
428 avc->ownslock = getpid();
431 slp->type = LockWrite;
434 avc->flockCount = -1;
436 slp->type = LockRead;
437 slp->next = avc->slocks;
442 lockIdSet(&flock, slp, clid);
445 /* now, if we got EWOULDBLOCK, and we're supposed to wait, we do */
446 if (((code == EWOULDBLOCK) || (code == EAGAIN) ||
447 (code == UAEWOULDBLOCK) || (code == UAEAGAIN))
448 && !(acom & LOCK_NB)) {
449 /* sleep for a second, allowing interrupts */
450 ReleaseWriteLock(&avc->lock);
451 #if defined(AFS_SGI_ENV)
452 AFS_RWUNLOCK((vnode_t *) avc, VRWLOCK_WRITE);
454 code = afs_osi_Wait(1000, NULL, 1);
455 #if defined(AFS_SGI_ENV)
456 AFS_RWLOCK((vnode_t *) avc, VRWLOCK_WRITE);
458 ObtainWriteLock(&avc->lock, 120);
460 code = EINTR; /* return this if ^C typed */
467 ReleaseWriteLock(&avc->lock);
468 code = afs_CheckCode(code, areq, 1); /* defeat a buggy AIX optimization */
473 /* warn a user that a lock has been ignored */
474 afs_int32 lastWarnTime = 0; /* this is used elsewhere */
478 register afs_int32 now;
481 AFS_STATCNT(DoLockWarning);
482 /* check if we've already warned someone recently */
483 if (now < lastWarnTime + 120)
486 /* otherwise, it is time to nag the user */
488 #ifdef AFS_LINUX26_ENV
490 ("afs: byte-range locks only enforced for processes on this machine.\n");
493 ("afs: byte-range lock/unlock ignored; make sure no one else is running this program.\n");
499 int afs_lockctl(struct vcache * avc, struct eflock * af, int flag,
500 struct AFS_UCRED * acred, pid_t clid, off_t offset)
501 #elif defined(AFS_SGI_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
502 int afs_lockctl(struct vcache * avc, struct AFS_FLOCK * af, int acmd,
503 struct AFS_UCRED * acred, pid_t clid)
506 int afs_lockctl(struct vcache * avc, struct AFS_FLOCK * af, int acmd,
507 struct AFS_UCRED * acred)
510 struct vrequest treq;
515 struct afs_fakestat_state fakestate;
517 AFS_STATCNT(afs_lockctl);
518 if ((code = afs_InitReq(&treq, acred)))
520 afs_InitFakeStat(&fakestate);
524 code = afs_EvalFakeStat(&avc, &fakestate, &treq);
529 if (flag & VNOFLCK) {
533 if (flag & CLNFLCK) {
535 } else if ((flag & GETFLCK) || (flag & RGETFLCK)) {
537 } else if ((flag & SETFLCK) || (flag & RSETFLCK)) {
541 #if (defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)) && !defined(AFS_SUN58_ENV)
542 if ((acmd == F_GETLK) || (acmd == F_RGETLK)) {
544 if (acmd == F_GETLK) {
546 if (af->l_type == F_UNLCK) {
550 #ifndef AFS_OSF_ENV /* getlock is a no-op for osf (for now) */
551 code = HandleGetLock(avc, af, &treq, clid);
553 code = afs_CheckCode(code, &treq, 2); /* defeat buggy AIX optimz */
555 } else if ((acmd == F_SETLK) || (acmd == F_SETLKW)
556 #if (defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)) && !defined(AFS_SUN58_ENV)
557 || (acmd == F_RSETLK) || (acmd == F_RSETLKW)) {
561 /* this next check is safer when left out, but more applications work
562 * with it in. However, they fail in race conditions. The question is
563 * what to do for people who don't have source to their application;
564 * this way at least, they can get work done */
565 #ifdef AFS_LINUX24_ENV
566 if (af->l_len == OFFSET_MAX)
567 af->l_len = 0; /* since some systems indicate it as EOF */
569 if (af->l_len == 0x7fffffff)
570 af->l_len = 0; /* since some systems indicate it as EOF */
571 #ifdef AFS_LINUX_64BIT_KERNEL
572 if (af->l_len == LONG_MAX)
573 af->l_len = 0; /* since some systems indicate it as EOF */
576 /* Java VMs ask for l_len=(long)-1 regardless of OS/CPU; bottom 32 bits
577 * sometimes get masked off by OS */
578 if ((sizeof(af->l_len) == 8) && (af->l_len == 0x7ffffffffffffffeLL))
580 /* next line makes byte range locks always succeed,
581 * even when they should block */
582 if (af->l_whence != 0 || af->l_start != 0 || af->l_len != 0) {
587 /* otherwise we can turn this into a whole-file flock */
588 if (af->l_type == F_RDLCK)
590 else if (af->l_type == F_WRLCK)
592 else if (af->l_type == F_UNLCK)
595 afs_PutFakeStat(&fakestate);
596 return EINVAL; /* unknown lock type */
598 if (((acmd == F_SETLK)
599 #if (defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)) && !defined(AFS_SUN58_ENV)
600 || (acmd == F_RSETLK)
602 ) && code != LOCK_UN)
603 code |= LOCK_NB; /* non-blocking, s.v.p. */
604 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV)
605 code = HandleFlock(avc, code, &treq, clid, 0 /*!onlymine */ );
606 #elif defined(AFS_SGI_ENV)
607 AFS_RWLOCK((vnode_t *) avc, VRWLOCK_WRITE);
608 code = HandleFlock(avc, code, &treq, clid, 0 /*!onlymine */ );
609 AFS_RWUNLOCK((vnode_t *) avc, VRWLOCK_WRITE);
611 code = HandleFlock(avc, code, &treq, 0, 0 /*!onlymine */ );
613 code = afs_CheckCode(code, &treq, 3); /* defeat AIX -O bug */
618 afs_PutFakeStat(&fakestate);
625 * Get a description of the first lock which would
626 * block the lock specified. If the specified lock
627 * would succeed, fill in the lock structure with 'F_UNLCK'.
629 * To do that, we have to ask the server for the lock
631 * 1. The file is not locked by this machine.
632 * 2. Asking for write lock, and only the current
633 * PID has the file read locked.
635 #ifndef AFS_OSF_ENV /* getlock is a no-op for osf (for now) */
637 HandleGetLock(register struct vcache *avc, register struct AFS_FLOCK *af,
638 register struct vrequest *areq, int clid)
640 register afs_int32 code;
641 struct AFS_FLOCK flock;
643 lockIdSet(&flock, NULL, clid);
645 ObtainWriteLock(&avc->lock, 122);
646 if (avc->flockCount == 0) {
648 * We don't know ourselves, so ask the server. Unfortunately, we
649 * don't know the pid. Not even the server knows the pid. Besides,
650 * the process with the lock is on another machine
652 code = GetFlockCount(avc, areq);
653 if (code == 0 || (af->l_type == F_RDLCK && code > 0)) {
654 af->l_type = F_UNLCK;
658 af->l_type = F_RDLCK;
660 af->l_type = F_WRLCK;
663 #if defined(AFS_HAVE_FLOCK_SYSID)
669 if (af->l_type == F_RDLCK) {
671 * We want a read lock. If there are only
672 * read locks, or we are the one with the
673 * write lock, say it is unlocked.
675 if (avc->flockCount > 0 || /* only read locks */
676 !lockIdcmp2(&flock, avc, NULL, 1, clid)) {
677 af->l_type = F_UNLCK;
681 /* one write lock, but who? */
682 af->l_type = F_WRLCK; /* not us, so lock would block */
683 if (avc->slocks) { /* we know who, so tell */
684 af->l_pid = avc->slocks->pid;
685 #if defined(AFS_HAVE_FLOCK_SYSID)
686 af->l_sysid = avc->slocks->sysid;
689 af->l_pid = 0; /* XXX can't happen?? */
690 #if defined(AFS_HAVE_FLOCK_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;
730 af->l_type = F_RDLCK;
732 #if defined(AFS_HAVE_FLOCK_SYSID)
735 /* find a pid that isn't our own */
736 for (slp = avc->slocks; slp; slp = slp->next) {
737 if (lockIdcmp2(&flock, NULL, slp, 1, clid)) {
738 af->l_pid = slp->pid;
739 #if defined(AFS_HAVE_FLOCK_SYSID)
740 af->l_sysid = avc->slocks->sysid;
749 * Ok, we want a write lock. If there is a write lock
750 * already, and it is not this process, we fail.
752 if (avc->flockCount < 0) {
753 if (lockIdcmp2(&flock, avc, NULL, 1, clid)) {
754 af->l_type = F_WRLCK;
756 af->l_pid = avc->slocks->pid;
757 #if defined(AFS_HAVE_FLOCK_SYSID)
758 af->l_sysid = avc->slocks->sysid;
761 af->l_pid = 0; /* XXX can't happen?? */
762 #if defined(AFS_HAVE_FLOCK_SYSID)
768 /* we are the one with the write lock */
769 af->l_type = F_UNLCK;
774 * Want a write lock, and we know there are read locks.
775 * If there is more than one, or it isn't us, we cannot lock.
777 if ((avc->flockCount > 1)
778 || lockIdcmp2(&flock, avc, NULL, 1, clid)) {
779 struct SimpleLocks *slp;
780 af->l_type = F_RDLCK;
782 #if defined(AFS_HAVE_FLOCK_SYSID)
785 /* find a pid that isn't our own */
786 for (slp = avc->slocks; slp; slp = slp->next) {
787 if (lockIdcmp2(&flock, NULL, slp, 1, clid)) {
788 af->l_pid = slp->pid;
789 #if defined(AFS_HAVE_FLOCK_SYSID)
790 af->l_sysid = avc->slocks->sysid;
799 * Want a write lock, and there is just one read lock, and it
800 * is this process with a read lock. Ask the server if there
801 * are any more processes with the file locked.
803 code = GetFlockCount(avc, areq);
804 if (code == 0 || code == 1) {
805 af->l_type = F_UNLCK;
809 af->l_type = F_RDLCK;
811 af->l_type = F_WRLCK;
813 #if defined(AFS_HAVE_FLOCK_SYSID)
820 af->l_len = 0; /* to end of file */
823 ReleaseWriteLock(&avc->lock);
827 /* Get the 'flock' count from the server. This comes back in a 'spare'
828 * field from a GetStatus RPC. If we have any problems with the RPC,
829 * we lie and say the file is unlocked. If we ask any 'old' fileservers,
830 * the spare field will be a zero, saying the file is unlocked. This is
831 * OK, as a further 'lock' request will do the right thing.
834 GetFlockCount(struct vcache *avc, struct vrequest *areq)
836 register struct afs_conn *tc;
837 register afs_int32 code;
838 struct AFSFetchStatus OutStatus;
839 struct AFSCallBack CallBack;
840 struct AFSVolSync tsync;
843 temp = areq->flags & O_NONBLOCK;
844 areq->flags |= O_NONBLOCK;
846 /* If we're disconnected, lie and say that we've got no locks. Ick */
847 if (AFS_IS_DISCONNECTED)
851 tc = afs_Conn(&avc->f.fid, areq, SHARED_LOCK);
853 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHSTATUS);
856 RXAFS_FetchStatus(tc->id, (struct AFSFid *)&avc->f.fid.Fid,
857 &OutStatus, &CallBack, &tsync);
863 (tc, code, &avc->f.fid, areq, AFS_STATS_FS_RPCIDX_FETCHSTATUS,
867 areq->flags &= ~O_NONBLOCK;
870 return (0); /* failed, say it is 'unlocked' */
872 return ((int)OutStatus.lockCount);
878 #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)
879 /* Flock not support on System V systems */
881 extern struct fileops afs_fileops;
884 afs_xflock(struct proc *p, void *args, int *retval)
885 #else /* AFS_OSF_ENV */
896 struct vrequest treq;
899 struct afs_fakestat_state fakestate;
901 afs_InitFakeStat(&fakestate);
902 AFS_STATCNT(afs_xflock);
905 uap = (struct a *)args;
906 getf(&fd, uap->fd, FILE_FLAGS_NULL, &u.u_file_state);
907 #else /* AFS_OSF_ENV */
908 uap = (struct a *)u.u_ap;
912 afs_PutFakeStat(&fakestate);
916 if (flockDone = afs_InitReq(&treq, u.u_cred)) {
917 afs_PutFakeStat(&fakestate);
923 /* first determine whether this is any sort of vnode */
924 if (fd->f_type == DTYPE_VNODE) {
925 /* good, this is a vnode; next see if it is an AFS vnode */
926 tvc = VTOAFS(fd->f_data); /* valid, given a vnode */
927 if (IsAfsVnode(AFSTOV(tvc))) {
928 /* This is an AFS vnode, so do the work */
929 code = afs_EvalFakeStat(&tvc, &fakestate, &treq);
932 afs_PutFakeStat(&fakestate);
935 if ((fd->f_flag & (FEXLOCK | FSHLOCK)) && !(uap->com & LOCK_UN)) {
936 /* First, if fd already has lock, release it for relock path */
937 #if defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV)
938 HandleFlock(tvc, LOCK_UN, &treq, u.u_procp->p_pid,
941 HandleFlock(tvc, LOCK_UN, &treq, 0, 0 /*!onlymine */ );
943 fd->f_flag &= ~(FEXLOCK | FSHLOCK);
945 /* now try the requested operation */
947 #if defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV)
949 HandleFlock(tvc, uap->com, &treq, u.u_procp->p_pid,
952 code = HandleFlock(tvc, uap->com, &treq, 0, 0 /*!onlymine */ );
958 if (uap->com & LOCK_UN) {
960 fd->f_flag &= ~(FEXLOCK | FSHLOCK);
964 #else /* AFS_OSF_ENV */
967 if (uap->com & LOCK_SH)
968 fd->f_flag |= FSHLOCK;
969 else if (uap->com & LOCK_EX)
970 fd->f_flag |= FEXLOCK;
974 fd->f_ops = &afs_fileops;
979 code = flock(p, args, retval);
986 afs_PutFakeStat(&fakestate);
988 #else /* AFS_OSF_ENV */
992 afs_PutFakeStat(&fakestate);
996 #endif /* !defined(AFS_AIX_ENV) && !defined(AFS_HPUX_ENV) && !defined(AFS_SUN5_ENV) && !defined(UKERNEL) && !defined(AFS_LINUX20_ENV) */