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 "../afs/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_FBSD_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_FBSD_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_FBSD_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_FBSD_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_FBSD_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_AIX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
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_FBSD_ENV)
465 afs_lockctl(struct vcache *avc, struct AFS_FLOCK *af, int acmd, struct AFS_UCRED *acred, pid_t clid)
469 afs_lockctl(struct vcache *avc, struct AFS_FLOCK *af, int acmd, struct AFS_UCRED *acred)
473 struct vrequest treq;
478 struct afs_fakestat_state fakestate;
480 AFS_STATCNT(afs_lockctl);
481 if ((code = afs_InitReq(&treq, acred))) return code;
482 afs_InitFakeStat(&fakestate);
483 code = afs_EvalFakeStat(&avc, &fakestate, &treq);
485 afs_PutFakeStat(&fakestate);
489 if (flag & VNOFLCK) {
490 afs_PutFakeStat(&fakestate);
493 if (flag & CLNFLCK) {
495 } else if ((flag & GETFLCK) || (flag & RGETFLCK)) {
497 } else if ((flag & SETFLCK) || (flag & RSETFLCK)) {
501 #if (defined(AFS_SUN_ENV) || defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)) && !defined(AFS_SUN58_ENV)
502 if ((acmd == F_GETLK) || (acmd == F_RGETLK)) {
504 if (acmd == F_GETLK) {
506 if (af->l_type == F_UNLCK) {
507 afs_PutFakeStat(&fakestate);
510 #ifndef AFS_OSF_ENV /* getlock is a no-op for osf (for now) */
511 code = HandleGetLock(avc, af, &treq, clid);
513 code = afs_CheckCode(code, &treq, 2); /* defeat buggy AIX optimz */
514 afs_PutFakeStat(&fakestate);
517 else if ((acmd == F_SETLK) || (acmd == F_SETLKW)
518 #if (defined(AFS_SUN_ENV) || defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)) && !defined(AFS_SUN58_ENV)
519 || (acmd == F_RSETLK)|| (acmd == F_RSETLKW)) {
523 /* this next check is safer when left out, but more applications work
524 with it in. However, they fail in race conditions. The question is
525 what to do for people who don't have source to their application;
526 this way at least, they can get work done */
527 #ifdef AFS_LINUX24_ENV
528 if (af->l_len == OFFSET_MAX)
529 af->l_len = 0; /* since some systems indicate it as EOF */
531 if (af->l_len == 0x7fffffff)
532 af->l_len = 0; /* since some systems indicate it as EOF */
533 #ifdef AFS_LINUX_64BIT_KERNEL
534 if (af->l_len == LONG_MAX)
535 af->l_len = 0; /* since some systems indicate it as EOF */
538 /* next line makes byte range locks always succeed,
539 even when they should block */
540 if (af->l_whence != 0 || af->l_start != 0 || af->l_len != 0) {
542 afs_PutFakeStat(&fakestate);
545 /* otherwise we can turn this into a whole-file flock */
546 if (af->l_type == F_RDLCK) code = LOCK_SH;
547 else if (af->l_type == F_WRLCK) code = LOCK_EX;
548 else if (af->l_type == F_UNLCK) code = LOCK_UN;
550 afs_PutFakeStat(&fakestate);
551 return EINVAL; /* unknown lock type */
553 if (((acmd == F_SETLK)
554 #if (defined(AFS_SGI_ENV) || defined(AFS_SUN_ENV)) && !defined(AFS_SUN58_ENV)
555 || (acmd == F_RSETLK)
557 ) && code != LOCK_UN)
558 code |= LOCK_NB; /* non-blocking, s.v.p. */
559 #if defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV)
560 code = HandleFlock(avc, code, &treq, clid, 0/*!onlymine*/);
562 #if defined(AFS_SGI_ENV)
563 AFS_RWLOCK((vnode_t *)avc, VRWLOCK_WRITE);
564 code = HandleFlock(avc, code, &treq, clid, 0/*!onlymine*/);
565 AFS_RWUNLOCK((vnode_t *)avc, VRWLOCK_WRITE);
567 code = HandleFlock(avc, code, &treq, 0, 0/*!onlymine*/);
570 code = afs_CheckCode(code, &treq, 3); /* defeat AIX -O bug */
571 afs_PutFakeStat(&fakestate);
574 afs_PutFakeStat(&fakestate);
580 * Get a description of the first lock which would
581 * block the lock specified. If the specified lock
582 * would succeed, fill in the lock structure with 'F_UNLCK'.
584 * To do that, we have to ask the server for the lock
586 * 1. The file is not locked by this machine.
587 * 2. Asking for write lock, and only the current
588 * PID has the file read locked.
590 #ifndef AFS_OSF_ENV /* getlock is a no-op for osf (for now) */
591 static int HandleGetLock(register struct vcache *avc,
592 register struct AFS_FLOCK *af, register struct vrequest *areq, int clid)
594 register afs_int32 code;
595 struct AFS_FLOCK flock;
597 lockIdSet(&flock, NULL, clid);
599 ObtainWriteLock(&avc->lock,122);
600 if (avc->flockCount == 0) {
601 /* We don't know ourselves, so ask the server. Unfortunately, we don't know the pid.
602 * Not even the server knows the pid. Besides, the process with the lock is on another machine
604 code = GetFlockCount(avc, areq);
605 if (code == 0 || (af->l_type == F_RDLCK && code > 0)) {
606 af->l_type = F_UNLCK;
610 af->l_type = F_RDLCK;
612 af->l_type = F_WRLCK;
615 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
621 if (af->l_type == F_RDLCK) {
623 * We want a read lock. If there are only
624 * read locks, or we are the one with the
625 * write lock, say it is unlocked.
627 if (avc->flockCount > 0 || /* only read locks */
628 !lockIdcmp2(&flock, avc, NULL, 1, clid)) {
629 af->l_type = F_UNLCK;
633 /* one write lock, but who? */
634 af->l_type = F_WRLCK; /* not us, so lock would block */
635 if (avc->slocks) { /* we know who, so tell */
636 af->l_pid = avc->slocks->pid;
637 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
638 af->l_sysid = avc->slocks->sysid;
641 af->l_pid = 0; /* XXX can't happen?? */
642 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
650 * Ok, we want a write lock. If there is a write lock
651 * already, and it is not this process, we fail.
653 if (avc->flockCount < 0) {
654 if (lockIdcmp2(&flock, avc, NULL, 1, clid)) {
655 af->l_type = F_WRLCK;
657 af->l_pid = avc->slocks->pid;
658 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
659 af->l_sysid = avc->slocks->sysid;
662 af->l_pid = 0; /* XXX can't happen?? */
663 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
669 /* we are the one with the write lock */
670 af->l_type = F_UNLCK;
675 * Want a write lock, and we know there are read locks.
676 * If there is more than one, or it isn't us, we cannot lock.
678 if ((avc->flockCount > 1)
679 || lockIdcmp2(&flock, avc, NULL, 1, clid)) {
680 struct SimpleLocks *slp;
682 af->l_type = F_RDLCK;
684 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
687 /* find a pid that isn't our own */
688 for (slp = avc->slocks; slp; slp = slp->next) {
689 if (lockIdcmp2(&flock, NULL, slp, 1, clid)) {
690 af->l_pid = slp->pid;
691 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
692 af->l_sysid = avc->slocks->sysid;
701 * Ok, we want a write lock. If there is a write lock
702 * already, and it is not this process, we fail.
704 if (avc->flockCount < 0) {
705 if (lockIdcmp2(&flock, avc, NULL, 1, clid)) {
706 af->l_type = F_WRLCK;
708 af->l_pid = avc->slocks->pid;
709 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
710 af->l_sysid = avc->slocks->sysid;
713 af->l_pid = 0; /* XXX can't happen?? */
714 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
720 /* we are the one with the write lock */
721 af->l_type = F_UNLCK;
726 * Want a write lock, and we know there are read locks.
727 * If there is more than one, or it isn't us, we cannot lock.
729 if ((avc->flockCount > 1)
730 || lockIdcmp2(&flock, avc, NULL, 1, clid)) {
731 struct SimpleLocks *slp;
732 af->l_type = F_RDLCK;
734 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
737 /* find a pid that isn't our own */
738 for (slp = avc->slocks; slp; slp = slp->next) {
739 if (lockIdcmp2(&flock, NULL, slp, 1, clid)) {
740 af->l_pid = slp->pid;
741 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
742 af->l_sysid = avc->slocks->sysid;
751 * Want a write lock, and there is just one read lock, and it
752 * is this process with a read lock. Ask the server if there
753 * are any more processes with the file locked.
755 code = GetFlockCount(avc, areq);
756 if (code == 0 || code == 1) {
757 af->l_type = F_UNLCK;
761 af->l_type = F_RDLCK;
763 af->l_type = F_WRLCK;
765 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
772 af->l_len = 0; /* to end of file */
775 ReleaseWriteLock(&avc->lock);
779 /* Get the 'flock' count from the server. This comes back in a 'spare'
780 * field from a GetStatus RPC. If we have any problems with the RPC,
781 * we lie and say the file is unlocked. If we ask any 'old' fileservers,
782 * the spare field will be a zero, saying the file is unlocked. This is
783 * OK, as a further 'lock' request will do the right thing.
785 static int GetFlockCount(struct vcache *avc, struct vrequest *areq)
787 register struct conn *tc;
788 register afs_int32 code;
789 struct AFSFetchStatus OutStatus;
790 struct AFSCallBack CallBack;
791 struct AFSVolSync tsync;
795 temp = areq->flags & O_NONBLOCK;
796 areq->flags |= O_NONBLOCK;
799 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
801 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHSTATUS);
803 code = RXAFS_FetchStatus(tc->id, (struct AFSFid *) &avc->fid.Fid,
804 &OutStatus, &CallBack, &tsync);
809 (afs_Analyze(tc, code, &avc->fid, areq,
810 AFS_STATS_FS_RPCIDX_FETCHSTATUS,
814 areq->flags &= ~O_NONBLOCK;
817 return(0); /* failed, say it is 'unlocked' */
819 return((int)OutStatus.lockCount);
825 #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_FBSD_ENV)
826 /* Flock not support on System V systems */
828 extern struct fileops afs_fileops;
830 int afs_xflock (struct proc *p, void *args, int *retval)
831 #else /* AFS_OSF_ENV */
832 int afs_xflock (void)
841 struct vrequest treq;
844 struct afs_fakestat_state fakestate;
846 afs_InitFakeStat(&fakestate);
847 AFS_STATCNT(afs_xflock);
850 uap = (struct a *)args;
851 getf(&fd, uap->fd, FILE_FLAGS_NULL, &u.u_file_state);
852 #else /* AFS_OSF_ENV */
853 uap = (struct a *)u.u_ap;
857 afs_PutFakeStat(&fakestate);
861 if (flockDone = afs_InitReq(&treq, u.u_cred)) {
862 afs_PutFakeStat(&fakestate);
865 /* first determine whether this is any sort of vnode */
866 if (fd->f_type == DTYPE_VNODE) {
867 /* good, this is a vnode; next see if it is an AFS vnode */
868 tvc = VTOAFS(fd->f_data); /* valid, given a vnode */
869 if (IsAfsVnode(AFSTOV(tvc))) {
870 /* This is an AFS vnode, so do the work */
872 /* find real vcache entry; shouldn't be null if gnode ref count
875 tvc = VTOAFS(afs_gntovn)(tvc);
878 afs_PutFakeStat(&fakestate);
882 code = afs_EvalFakeStat(&tvc, &fakestate, &treq);
884 afs_PutFakeStat(&fakestate);
887 if ((fd->f_flag & (FEXLOCK | FSHLOCK)) && !(uap->com & LOCK_UN)) {
888 /* First, if fd already has lock, release it for relock path */
889 #if defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV) || (defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV))
890 HandleFlock(tvc, LOCK_UN, &treq, u.u_procp->p_pid, 0/*!onlymine*/);
892 HandleFlock(tvc, LOCK_UN, &treq, 0, 0/*!onlymine*/);
894 fd->f_flag &= ~(FEXLOCK | FSHLOCK);
896 /* now try the requested operation */
898 #if defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV) || (defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV))
899 code = HandleFlock(tvc, uap->com, &treq,
900 u.u_procp->p_pid, 0/*!onlymine*/);
902 code = HandleFlock(tvc, uap->com, &treq, 0, 0/*!onlymine*/);
908 if (uap->com & LOCK_UN) {
910 fd->f_flag &= ~(FEXLOCK | FSHLOCK);
915 #else /* AFS_OSF_ENV */
918 if (uap->com & LOCK_SH) fd->f_flag |= FSHLOCK;
919 else if (uap->com & LOCK_EX) fd->f_flag |= FEXLOCK;
923 fd->f_ops = &afs_fileops;
928 code = flock(p, args, retval);
934 afs_PutFakeStat(&fakestate);
936 #else /* AFS_OSF_ENV */
939 (*afs_longcall_procs.LC_flock)();
943 afs_PutFakeStat(&fakestate);
947 #endif /* !defined(AFS_AIX_ENV) && !defined(AFS_HPUX_ENV) && !defined(AFS_SUN5_ENV) && !defined(UKERNEL) && !defined(AFS_LINUX20_ENV) */