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 /* clid - nonzero on sgi sunos osf1 only */
225 HandleFlock(register struct vcache *avc, int acom, struct vrequest *areq,
226 pid_t clid, int onlymine)
229 struct SimpleLocks *slp, *tlp, **slpp;
231 struct AFSVolSync tsync;
233 struct AFS_FLOCK flock;
235 AFS_STATCNT(HandleFlock);
236 code = 0; /* default when we don't make any network calls */
237 lockIdSet(&flock, NULL, clid);
239 #if defined(AFS_SGI_ENV)
240 osi_Assert(valusema(&avc->vc_rwlock) <= 0);
241 osi_Assert(OSI_GET_LOCKID() == avc->vc_rwlockid);
243 ObtainWriteLock(&avc->lock, 118);
244 if (acom & LOCK_UN) {
249 /* If the lock is held exclusive, then only the owning process
250 * or a child can unlock it. Use pid and ppid because they are
251 * unique identifiers.
253 if ((avc->flockCount < 0) && (getpid() != avc->ownslock)) {
255 if (onlymine || (getppid() != avc->ownslock)) {
257 if (onlymine || (u.u_procp->p_ppid != avc->ownslock)) {
259 ReleaseWriteLock(&avc->lock);
264 if (lockIdcmp2(&flock, avc, NULL, onlymine, clid)) {
265 ReleaseWriteLock(&avc->lock);
271 if (avc->flockCount == 0) {
272 ReleaseWriteLock(&avc->lock);
276 /* unlock the lock */
277 if (avc->flockCount > 0) {
279 for (slp = *slpp; slp;) {
280 if (!lockIdcmp2(&flock, avc, slp, onlymine, clid)) {
282 tlp = *slpp = slp->next;
283 osi_FreeSmallSpace(slp);
290 } else if (avc->flockCount == -1) {
291 afs_StoreAllSegments(avc, areq, AFS_ASYNC); /* fsync file early */
293 /* And remove the (only) exclusive lock entry from the list... */
294 osi_FreeSmallSpace(avc->slocks);
297 if (avc->flockCount == 0) {
299 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
301 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_RELEASELOCK);
303 code = RXAFS_ReleaseLock(tc->id, (struct AFSFid *)
304 &avc->fid.Fid, &tsync);
310 (tc, code, &avc->fid, areq,
311 AFS_STATS_FS_RPCIDX_RELEASELOCK, SHARED_LOCK, NULL));
314 while (1) { /* set a new lock */
316 * Upgrading from shared locks to Exclusive and vice versa
317 * is a bit tricky and we don't really support it yet. But
318 * we try to support the common used one which is upgrade
319 * a shared lock to an exclusive for the same process...
321 if ((avc->flockCount > 0 && (acom & LOCK_EX))
322 || (avc->flockCount == -1 && (acom & LOCK_SH))) {
324 * Upgrading from shared locks to an exclusive one:
325 * For now if all the shared locks belong to the
326 * same process then we unlock them on the server
327 * and proceed with the upgrade. Unless we change the
328 * server's locking interface impl we prohibit from
329 * unlocking other processes's shared locks...
330 * Upgrading from an exclusive lock to a shared one:
331 * Again only allowed to be done by the same process.
334 for (slp = *slpp; slp;) {
336 (&flock, avc, slp, 1 /*!onlymine */ , clid)) {
341 tlp = *slpp = slp->next;
342 osi_FreeSmallSpace(slp);
350 if (!code && avc->flockCount == 0) {
352 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
355 (AFS_STATS_FS_RPCIDX_RELEASELOCK);
358 RXAFS_ReleaseLock(tc->id,
359 (struct AFSFid *)&avc->fid.
366 (tc, code, &avc->fid, areq,
367 AFS_STATS_FS_RPCIDX_RELEASELOCK, SHARED_LOCK,
370 } else if (avc->flockCount == -1 && (acom & LOCK_EX)) {
371 if (lockIdcmp2(&flock, avc, NULL, 1, clid)) {
377 /* compatible here, decide if needs to go to file server. If
378 * we've already got the file locked (and thus read-locked, since
379 * we've already checked for compatibility), we shouldn't send
380 * the call through to the server again */
381 if (avc->flockCount == 0) {
382 /* we're the first on our block, send the call through */
383 lockType = ((acom & LOCK_EX) ? LockWrite : LockRead);
385 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
387 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETLOCK);
389 code = RXAFS_SetLock(tc->id, (struct AFSFid *)
390 &avc->fid.Fid, lockType,
397 (tc, code, &avc->fid, areq,
398 AFS_STATS_FS_RPCIDX_SETLOCK, SHARED_LOCK,
401 code = 0; /* otherwise, pretend things worked */
404 slp = (struct SimpleLocks *)
405 osi_AllocSmallSpace(sizeof(struct SimpleLocks));
406 if (acom & LOCK_EX) {
411 /* Record unique id of process owning exclusive lock. */
412 avc->ownslock = getpid();
415 slp->type = LockWrite;
418 avc->flockCount = -1;
420 slp->type = LockRead;
421 slp->next = avc->slocks;
426 lockIdSet(&flock, slp, clid);
429 /* now, if we got EWOULDBLOCK, and we're supposed to wait, we do */
430 if (((code == EWOULDBLOCK) || (code == EAGAIN) ||
431 (code == UAEWOULDBLOCK) || (code == UAEAGAIN))
432 && !(acom & LOCK_NB)) {
433 /* sleep for a second, allowing interrupts */
434 ReleaseWriteLock(&avc->lock);
435 #if defined(AFS_SGI_ENV)
436 AFS_RWUNLOCK((vnode_t *) avc, VRWLOCK_WRITE);
438 code = afs_osi_Wait(1000, NULL, 1);
439 #if defined(AFS_SGI_ENV)
440 AFS_RWLOCK((vnode_t *) avc, VRWLOCK_WRITE);
442 ObtainWriteLock(&avc->lock, 120);
444 code = EINTR; /* return this if ^C typed */
451 ReleaseWriteLock(&avc->lock);
452 code = afs_CheckCode(code, areq, 1); /* defeat a buggy AIX optimization */
457 /* warn a user that a lock has been ignored */
458 afs_int32 lastWarnTime = 0; /* this is used elsewhere */
462 register afs_int32 now;
465 AFS_STATCNT(DoLockWarning);
466 /* check if we've already warned someone recently */
467 if (now < lastWarnTime + 120)
470 /* otherwise, it is time to nag the user */
473 ("afs: byte-range lock/unlock ignored; make sure no one else is running this program.\n");
478 int afs_lockctl(struct vcache * avc, struct eflock * af, int flag,
479 struct AFS_UCRED * acred, pid_t clid, off_t offset)
480 #elif defined(AFS_SGI_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
481 int afs_lockctl(struct vcache * avc, struct AFS_FLOCK * af, int acmd,
482 struct AFS_UCRED * acred, pid_t clid)
485 int afs_lockctl(struct vcache * avc, struct AFS_FLOCK * af, int acmd,
486 struct AFS_UCRED * acred)
489 struct vrequest treq;
494 struct afs_fakestat_state fakestate;
496 AFS_STATCNT(afs_lockctl);
497 if ((code = afs_InitReq(&treq, acred)))
499 afs_InitFakeStat(&fakestate);
500 code = afs_EvalFakeStat(&avc, &fakestate, &treq);
502 afs_PutFakeStat(&fakestate);
506 if (flag & VNOFLCK) {
507 afs_PutFakeStat(&fakestate);
510 if (flag & CLNFLCK) {
512 } else if ((flag & GETFLCK) || (flag & RGETFLCK)) {
514 } else if ((flag & SETFLCK) || (flag & RSETFLCK)) {
518 #if (defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)) && !defined(AFS_SUN58_ENV)
519 if ((acmd == F_GETLK) || (acmd == F_RGETLK)) {
521 if (acmd == F_GETLK) {
523 if (af->l_type == F_UNLCK) {
524 afs_PutFakeStat(&fakestate);
527 #ifndef AFS_OSF_ENV /* getlock is a no-op for osf (for now) */
528 code = HandleGetLock(avc, af, &treq, clid);
530 code = afs_CheckCode(code, &treq, 2); /* defeat buggy AIX optimz */
531 afs_PutFakeStat(&fakestate);
533 } else if ((acmd == F_SETLK) || (acmd == F_SETLKW)
534 #if (defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)) && !defined(AFS_SUN58_ENV)
535 || (acmd == F_RSETLK) || (acmd == F_RSETLKW)) {
539 /* this next check is safer when left out, but more applications work
540 * with it in. However, they fail in race conditions. The question is
541 * what to do for people who don't have source to their application;
542 * this way at least, they can get work done */
543 #ifdef AFS_LINUX24_ENV
544 if (af->l_len == OFFSET_MAX)
545 af->l_len = 0; /* since some systems indicate it as EOF */
547 if (af->l_len == 0x7fffffff)
548 af->l_len = 0; /* since some systems indicate it as EOF */
549 #ifdef AFS_LINUX_64BIT_KERNEL
550 if (af->l_len == LONG_MAX)
551 af->l_len = 0; /* since some systems indicate it as EOF */
554 /* Java VMs ask for l_len=(long)-1 regardless of OS/CPU; bottom 32 bits
555 * sometimes get masked off by OS */
556 if ((sizeof(af->l_len) == 8) && (af->l_len == 0x7ffffffffffffffe))
558 /* next line makes byte range locks always succeed,
559 * even when they should block */
560 if (af->l_whence != 0 || af->l_start != 0 || af->l_len != 0) {
562 afs_PutFakeStat(&fakestate);
565 /* otherwise we can turn this into a whole-file flock */
566 if (af->l_type == F_RDLCK)
568 else if (af->l_type == F_WRLCK)
570 else if (af->l_type == F_UNLCK)
573 afs_PutFakeStat(&fakestate);
574 return EINVAL; /* unknown lock type */
576 if (((acmd == F_SETLK)
577 #if (defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)) && !defined(AFS_SUN58_ENV)
578 || (acmd == F_RSETLK)
580 ) && code != LOCK_UN)
581 code |= LOCK_NB; /* non-blocking, s.v.p. */
582 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV)
583 code = HandleFlock(avc, code, &treq, clid, 0 /*!onlymine */ );
584 #elif defined(AFS_SGI_ENV)
585 AFS_RWLOCK((vnode_t *) avc, VRWLOCK_WRITE);
586 code = HandleFlock(avc, code, &treq, clid, 0 /*!onlymine */ );
587 AFS_RWUNLOCK((vnode_t *) avc, VRWLOCK_WRITE);
589 code = HandleFlock(avc, code, &treq, 0, 0 /*!onlymine */ );
591 code = afs_CheckCode(code, &treq, 3); /* defeat AIX -O bug */
592 afs_PutFakeStat(&fakestate);
595 afs_PutFakeStat(&fakestate);
601 * Get a description of the first lock which would
602 * block the lock specified. If the specified lock
603 * would succeed, fill in the lock structure with 'F_UNLCK'.
605 * To do that, we have to ask the server for the lock
607 * 1. The file is not locked by this machine.
608 * 2. Asking for write lock, and only the current
609 * PID has the file read locked.
611 #ifndef AFS_OSF_ENV /* getlock is a no-op for osf (for now) */
613 HandleGetLock(register struct vcache *avc, register struct AFS_FLOCK *af,
614 register struct vrequest *areq, int clid)
616 register afs_int32 code;
617 struct AFS_FLOCK flock;
619 lockIdSet(&flock, NULL, clid);
621 ObtainWriteLock(&avc->lock, 122);
622 if (avc->flockCount == 0) {
624 * We don't know ourselves, so ask the server. Unfortunately, we
625 * don't know the pid. Not even the server knows the pid. Besides,
626 * the process with the lock is on another machine
628 code = GetFlockCount(avc, areq);
629 if (code == 0 || (af->l_type == F_RDLCK && code > 0)) {
630 af->l_type = F_UNLCK;
634 af->l_type = F_RDLCK;
636 af->l_type = F_WRLCK;
639 #if defined(AFS_HAVE_FLOCK_SYSID)
645 if (af->l_type == F_RDLCK) {
647 * We want a read lock. If there are only
648 * read locks, or we are the one with the
649 * write lock, say it is unlocked.
651 if (avc->flockCount > 0 || /* only read locks */
652 !lockIdcmp2(&flock, avc, NULL, 1, clid)) {
653 af->l_type = F_UNLCK;
657 /* one write lock, but who? */
658 af->l_type = F_WRLCK; /* not us, so lock would block */
659 if (avc->slocks) { /* we know who, so tell */
660 af->l_pid = avc->slocks->pid;
661 #if defined(AFS_HAVE_FLOCK_SYSID)
662 af->l_sysid = avc->slocks->sysid;
665 af->l_pid = 0; /* XXX can't happen?? */
666 #if defined(AFS_HAVE_FLOCK_SYSID)
674 * Ok, we want a write lock. If there is a write lock
675 * already, and it is not this process, we fail.
677 if (avc->flockCount < 0) {
678 if (lockIdcmp2(&flock, avc, NULL, 1, clid)) {
679 af->l_type = F_WRLCK;
681 af->l_pid = avc->slocks->pid;
682 #if defined(AFS_HAVE_FLOCK_SYSID)
683 af->l_sysid = avc->slocks->sysid;
686 af->l_pid = 0; /* XXX can't happen?? */
687 #if defined(AFS_HAVE_FLOCK_SYSID)
693 /* we are the one with the write lock */
694 af->l_type = F_UNLCK;
699 * Want a write lock, and we know there are read locks.
700 * If there is more than one, or it isn't us, we cannot lock.
702 if ((avc->flockCount > 1)
703 || lockIdcmp2(&flock, avc, NULL, 1, clid)) {
704 struct SimpleLocks *slp;
706 af->l_type = F_RDLCK;
708 #if defined(AFS_HAVE_FLOCK_SYSID)
711 /* find a pid that isn't our own */
712 for (slp = avc->slocks; slp; slp = slp->next) {
713 if (lockIdcmp2(&flock, NULL, slp, 1, clid)) {
714 af->l_pid = slp->pid;
715 #if defined(AFS_HAVE_FLOCK_SYSID)
716 af->l_sysid = avc->slocks->sysid;
725 * Ok, we want a write lock. If there is a write lock
726 * already, and it is not this process, we fail.
728 if (avc->flockCount < 0) {
729 if (lockIdcmp2(&flock, avc, NULL, 1, clid)) {
730 af->l_type = F_WRLCK;
732 af->l_pid = avc->slocks->pid;
733 #if defined(AFS_HAVE_FLOCK_SYSID)
734 af->l_sysid = avc->slocks->sysid;
737 af->l_pid = 0; /* XXX can't happen?? */
738 #if defined(AFS_HAVE_FLOCK_SYSID)
744 /* we are the one with the write lock */
745 af->l_type = F_UNLCK;
750 * Want a write lock, and we know there are read locks.
751 * If there is more than one, or it isn't us, we cannot lock.
753 if ((avc->flockCount > 1)
754 || lockIdcmp2(&flock, avc, NULL, 1, clid)) {
755 struct SimpleLocks *slp;
756 af->l_type = F_RDLCK;
758 #if defined(AFS_HAVE_FLOCK_SYSID)
761 /* find a pid that isn't our own */
762 for (slp = avc->slocks; slp; slp = slp->next) {
763 if (lockIdcmp2(&flock, NULL, slp, 1, clid)) {
764 af->l_pid = slp->pid;
765 #if defined(AFS_HAVE_FLOCK_SYSID)
766 af->l_sysid = avc->slocks->sysid;
775 * Want a write lock, and there is just one read lock, and it
776 * is this process with a read lock. Ask the server if there
777 * are any more processes with the file locked.
779 code = GetFlockCount(avc, areq);
780 if (code == 0 || code == 1) {
781 af->l_type = F_UNLCK;
785 af->l_type = F_RDLCK;
787 af->l_type = F_WRLCK;
789 #if defined(AFS_HAVE_FLOCK_SYSID)
796 af->l_len = 0; /* to end of file */
799 ReleaseWriteLock(&avc->lock);
803 /* Get the 'flock' count from the server. This comes back in a 'spare'
804 * field from a GetStatus RPC. If we have any problems with the RPC,
805 * we lie and say the file is unlocked. If we ask any 'old' fileservers,
806 * the spare field will be a zero, saying the file is unlocked. This is
807 * OK, as a further 'lock' request will do the right thing.
810 GetFlockCount(struct vcache *avc, struct vrequest *areq)
812 register struct conn *tc;
813 register afs_int32 code;
814 struct AFSFetchStatus OutStatus;
815 struct AFSCallBack CallBack;
816 struct AFSVolSync tsync;
819 temp = areq->flags & O_NONBLOCK;
820 areq->flags |= O_NONBLOCK;
823 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
825 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHSTATUS);
828 RXAFS_FetchStatus(tc->id, (struct AFSFid *)&avc->fid.Fid,
829 &OutStatus, &CallBack, &tsync);
835 (tc, code, &avc->fid, areq, AFS_STATS_FS_RPCIDX_FETCHSTATUS,
839 areq->flags &= ~O_NONBLOCK;
842 return (0); /* failed, say it is 'unlocked' */
844 return ((int)OutStatus.lockCount);
850 #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)
851 /* Flock not support on System V systems */
853 extern struct fileops afs_fileops;
856 afs_xflock(struct proc *p, void *args, int *retval)
857 #else /* AFS_OSF_ENV */
868 struct vrequest treq;
871 struct afs_fakestat_state fakestate;
873 afs_InitFakeStat(&fakestate);
874 AFS_STATCNT(afs_xflock);
877 uap = (struct a *)args;
878 getf(&fd, uap->fd, FILE_FLAGS_NULL, &u.u_file_state);
879 #else /* AFS_OSF_ENV */
880 uap = (struct a *)u.u_ap;
884 afs_PutFakeStat(&fakestate);
888 if (flockDone = afs_InitReq(&treq, u.u_cred)) {
889 afs_PutFakeStat(&fakestate);
892 /* first determine whether this is any sort of vnode */
893 if (fd->f_type == DTYPE_VNODE) {
894 /* good, this is a vnode; next see if it is an AFS vnode */
895 tvc = VTOAFS(fd->f_data); /* valid, given a vnode */
896 if (IsAfsVnode(AFSTOV(tvc))) {
897 /* This is an AFS vnode, so do the work */
898 code = afs_EvalFakeStat(&tvc, &fakestate, &treq);
900 afs_PutFakeStat(&fakestate);
903 if ((fd->f_flag & (FEXLOCK | FSHLOCK)) && !(uap->com & LOCK_UN)) {
904 /* First, if fd already has lock, release it for relock path */
905 #if defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV)
906 HandleFlock(tvc, LOCK_UN, &treq, u.u_procp->p_pid,
909 HandleFlock(tvc, LOCK_UN, &treq, 0, 0 /*!onlymine */ );
911 fd->f_flag &= ~(FEXLOCK | FSHLOCK);
913 /* now try the requested operation */
915 #if defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV)
917 HandleFlock(tvc, uap->com, &treq, u.u_procp->p_pid,
920 code = HandleFlock(tvc, uap->com, &treq, 0, 0 /*!onlymine */ );
926 if (uap->com & LOCK_UN) {
928 fd->f_flag &= ~(FEXLOCK | FSHLOCK);
932 #else /* AFS_OSF_ENV */
935 if (uap->com & LOCK_SH)
936 fd->f_flag |= FSHLOCK;
937 else if (uap->com & LOCK_EX)
938 fd->f_flag |= FEXLOCK;
942 fd->f_ops = &afs_fileops;
947 code = flock(p, args, retval);
953 afs_PutFakeStat(&fakestate);
955 #else /* AFS_OSF_ENV */
958 afs_PutFakeStat(&fakestate);
962 #endif /* !defined(AFS_AIX_ENV) && !defined(AFS_HPUX_ENV) && !defined(AFS_SUN5_ENV) && !defined(UKERNEL) && !defined(AFS_LINUX20_ENV) */