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 #if defined(AFS_HPUX102_ENV)
28 #define AFS_FLOCK k_flock
30 #if defined(AFS_SUN56_ENV) || defined(AFS_LINUX24_ENV)
31 #define AFS_FLOCK flock64
33 #define AFS_FLOCK flock
34 #endif /* AFS_SUN65_ENV */
35 #endif /* AFS_HPUX102_ENV */
37 static int GetFlockCount(struct vcache *avc, struct vrequest *areq);
39 void lockIdSet(flock, slp, clid)
40 int clid; /* non-zero on SGI, OSF, SunOS */
41 struct SimpleLocks *slp;
42 struct AFS_FLOCK *flock;
44 #if defined(AFS_SUN5_ENV)
45 register proc_t *procp = ttoproc(curthread);
47 #if !defined(AFS_AIX41_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_SGI65_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
49 struct proc *procp = OSI_GET_CURRENT_PROCP();
51 struct proc *procp = u.u_procp;
52 #endif /* AFS_SGI_ENV */
55 #if defined(AFS_SGI65_ENV)
57 get_current_flid(&flid);
66 slp->sysid = u.u_sysid;
70 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV)
73 slp->pid = procp->p_pid;
75 slp->sysid = procp->p_sysid;
76 slp->pid = procp->p_epid;
79 #if defined(AFS_SGI_ENV)
81 slp->sysid = flid.fl_sysid;
83 slp->sysid = OSI_GET_CURRENT_SYSID();
87 #if defined(AFS_SUN_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
90 #if defined(AFS_LINUX20_ENV) || defined(AFS_HPUX_ENV)
93 slp->pid = u.u_procp->p_pid;
96 #endif /* AFS_AIX_ENV */
97 #endif /* AFS_AIX32_ENV */
100 #if defined(AFS_AIX32_ENV)
103 flock->l_pid = getpid();
105 flock->l_sysid = u.u_sysid;
106 flock->l_pid = u.u_epid;
109 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV)
112 flock->l_pid = procp->p_pid;
114 flock->l_sysid = procp->p_sysid;
115 flock->l_pid = procp->p_epid;
118 #if defined(AFS_SGI_ENV)
120 flock->l_sysid = flid.fl_sysid;
122 flock->l_sysid = OSI_GET_CURRENT_SYSID();
126 #if defined(AFS_SUN_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
129 #if defined(AFS_LINUX20_ENV) || defined(AFS_HPUX_ENV)
130 flock->l_pid = getpid();
132 flock->l_pid = u.u_procp->p_pid;
136 #endif /* AFS_AIX_ENV */
137 #endif /* AFS_AIX32_ENV */
141 /* return 1 (true) if specified flock does not match alp (if
142 * specified), or any of the slp structs (if alp == 0)
144 /* I'm not sure that the comparsion of flock->pid to p_ppid
145 * is correct. Should that be a comparision of alp (or slp) ->pid
146 * to p_ppid? Especially in the context of the lower loop, where
147 * the repeated comparison doesn't make much sense...
149 static int lockIdcmp2(flock1, vp, alp, onlymine, clid)
150 struct AFS_FLOCK *flock1;
152 register struct SimpleLocks *alp;
153 int onlymine; /* don't match any locks which are held by my */
155 int clid; /* Only Irix 6.5 for now. */
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_FBSD_ENV)
163 struct proc *procp = curprocp;
164 #else /* AFS_SGI64_ENV */
165 struct proc *procp = u.u_procp;
166 #endif /* AFS_SGI64_ENV */
172 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
173 if (flock1->l_sysid != alp->sysid) {
177 if ((flock1->l_pid == alp->pid) ||
178 #if defined(AFS_AIX41_ENV) || defined(AFS_LINUX20_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
179 (!onlymine && (flock1->l_pid == getppid()))
181 #if defined(AFS_SGI65_ENV)
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_AIX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
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 HandleFlock(avc, acom, areq, clid, onlymine)
222 pid_t clid; /* non-zero on SGI, SunOS, OSF1 only */
223 register struct vcache *avc;
224 struct vrequest *areq;
228 struct SimpleLocks *slp, *tlp, **slpp;
230 struct AFSVolSync tsync;
232 struct AFS_FLOCK flock;
235 AFS_STATCNT(HandleFlock);
236 code = 0; /* default when we don't make any network calls */
237 lockIdSet(&flock, (struct SimpleLocks *)0, 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, (struct SimpleLocks *)0, 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);
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) {
300 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
302 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_RELEASELOCK);
303 #ifdef RX_ENABLE_LOCKS
305 #endif /* RX_ENABLE_LOCKS */
306 code = RXAFS_ReleaseLock(tc->id, (struct AFSFid *)
307 &avc->fid.Fid, &tsync);
308 #ifdef RX_ENABLE_LOCKS
310 #endif /* RX_ENABLE_LOCKS */
315 (afs_Analyze(tc, code, &avc->fid, areq,
316 AFS_STATS_FS_RPCIDX_RELEASELOCK,
317 SHARED_LOCK, (struct cell *)0));
321 while (1) { /* set a new lock */
323 * Upgrading from shared locks to Exclusive and vice versa
324 * is a bit tricky and we don't really support it yet. But
325 * we try to support the common used one which is upgrade
326 * a shared lock to an exclusive for the same process...
328 if ((avc->flockCount > 0 && (acom & LOCK_EX)) ||
329 (avc->flockCount == -1 && (acom & LOCK_SH))) {
331 * Upgrading from shared locks to an exclusive one:
332 * For now if all the shared locks belong to the
333 * same process then we unlock them on the server
334 * and proceed with the upgrade. Unless we change the
335 * server's locking interface impl we prohibit from
336 * unlocking other processes's shared locks...
337 * Upgrading from an exclusive lock to a shared one:
338 * Again only allowed to be done by the same process.
341 for (slp = *slpp; slp;) {
342 if (!lockIdcmp2(&flock, avc, slp, 1/*!onlymine*/, clid)) {
347 tlp = *slpp = slp->next;
348 osi_FreeSmallSpace(slp);
356 if (!code && avc->flockCount == 0) {
358 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
360 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_RELEASELOCK);
361 #ifdef RX_ENABLE_LOCKS
363 #endif /* RX_ENABLE_LOCKS */
364 code = RXAFS_ReleaseLock(tc->id,
365 (struct AFSFid *) &avc->fid.Fid,
367 #ifdef RX_ENABLE_LOCKS
369 #endif /* RX_ENABLE_LOCKS */
374 (afs_Analyze(tc, code, &avc->fid, areq,
375 AFS_STATS_FS_RPCIDX_RELEASELOCK,
376 SHARED_LOCK, (struct cell *)0));
378 } else if (avc->flockCount == -1 && (acom & LOCK_EX)) {
379 if (lockIdcmp2(&flock, avc, (struct SimpleLocks *)0, 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);
393 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
395 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETLOCK);
396 #ifdef RX_ENABLE_LOCKS
398 #endif /* RX_ENABLE_LOCKS */
399 code = RXAFS_SetLock(tc->id, (struct AFSFid *)
400 &avc->fid.Fid, lockType, &tsync);
401 #ifdef RX_ENABLE_LOCKS
403 #endif /* RX_ENABLE_LOCKS */
408 (afs_Analyze(tc, code, &avc->fid, areq,
409 AFS_STATS_FS_RPCIDX_SETLOCK,
410 SHARED_LOCK, (struct cell *)0));
412 else code = 0; /* otherwise, pretend things worked */
415 slp = (struct SimpleLocks *) osi_AllocSmallSpace(sizeof(struct SimpleLocks));
416 if (acom & LOCK_EX) {
421 /* Record unique id of process owning exclusive lock. */
422 avc->ownslock = getpid();
425 slp->type = LockWrite;
426 slp->next = (struct SimpleLocks *)0;
428 avc->flockCount = -1;
430 slp->type = LockRead;
431 slp->next = avc->slocks;
436 lockIdSet(&flock, slp, clid);
439 /* now, if we got EWOULDBLOCK, and we're supposed to wait, we do */
440 if(((code == EWOULDBLOCK)||(code == EAGAIN)) && !(acom & LOCK_NB)) {
441 /* sleep for a second, allowing interrupts */
442 ReleaseWriteLock(&avc->lock);
443 #if defined(AFS_SGI_ENV)
444 AFS_RWUNLOCK((vnode_t *)avc, VRWLOCK_WRITE);
446 code = afs_osi_Wait(1000, (struct afs_osi_WaitHandle *) 0, 1);
447 #if defined(AFS_SGI_ENV)
448 AFS_RWLOCK((vnode_t *)avc, VRWLOCK_WRITE);
450 ObtainWriteLock(&avc->lock,120);
452 code = EINTR; /* return this if ^C typed */
459 ReleaseWriteLock(&avc->lock);
460 code = afs_CheckCode(code, areq, 1); /* defeat a buggy AIX optimization */
465 /* warn a user that a lock has been ignored */
466 afs_int32 lastWarnTime = 0;
467 static void DoLockWarning() {
468 register afs_int32 now;
471 AFS_STATCNT(DoLockWarning);
472 /* check if we've already warned someone recently */
473 if (now < lastWarnTime + 120) return;
475 /* otherwise, it is time to nag the user */
477 afs_warn("afs: byte-range lock/unlock ignored; make sure no one else is running this program.\n");
482 afs_lockctl(avc, af, flag, acred, clid, offset)
488 #if defined(AFS_SGI_ENV) || (defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV)) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
489 afs_lockctl(avc, af, acmd, acred, clid)
493 afs_lockctl(avc, af, acmd, acred)
495 struct AFS_FLOCK *af;
499 struct AFS_UCRED *acred; {
500 struct vrequest treq;
506 AFS_STATCNT(afs_lockctl);
507 if (code = afs_InitReq(&treq, acred)) return code;
509 if (flag & VNOFLCK) return 0;
510 if (flag & CLNFLCK) {
512 } else if ((flag & GETFLCK) || (flag & RGETFLCK)) {
514 } else if ((flag & SETFLCK) || (flag & RSETFLCK)) {
518 #if (defined(AFS_SUN_ENV) || 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)
525 #ifndef AFS_OSF_ENV /* getlock is a no-op for osf (for now) */
526 code = HandleGetLock(avc, af, &treq, clid);
528 code = afs_CheckCode(code, &treq, 2); /* defeat buggy AIX optimz */
531 else if ((acmd == F_SETLK) || (acmd == F_SETLKW)
532 #if (defined(AFS_SUN_ENV) || defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)) && !defined(AFS_SUN58_ENV)
533 || (acmd == F_RSETLK)|| (acmd == F_RSETLKW)) {
537 /* this next check is safer when left out, but more applications work
538 with it in. However, they fail in race conditions. The question is
539 what to do for people who don't have source to their application;
540 this way at least, they can get work done */
541 #ifdef AFS_LINUX24_ENV
542 if (af->l_len == OFFSET_MAX)
543 af->l_len = 0; /* since some systems indicate it as EOF */
545 if (af->l_len == 0x7fffffff)
546 af->l_len = 0; /* since some systems indicate it as EOF */
547 #ifdef AFS_LINUX_64BIT_KERNEL
548 if (af->l_len == LONG_MAX)
549 af->l_len = 0; /* since some systems indicate it as EOF */
552 /* next line makes byte range locks always succeed,
553 even when they should block */
554 if (af->l_whence != 0 || af->l_start != 0 || af->l_len != 0) {
558 /* otherwise we can turn this into a whole-file flock */
559 if (af->l_type == F_RDLCK) code = LOCK_SH;
560 else if (af->l_type == F_WRLCK) code = LOCK_EX;
561 else if (af->l_type == F_UNLCK) code = LOCK_UN;
562 else return EINVAL; /* unknown lock type */
563 if (((acmd == F_SETLK)
564 #if (defined(AFS_SGI_ENV) || defined(AFS_SUN_ENV)) && !defined(AFS_SUN58_ENV)
565 || (acmd == F_RSETLK)
567 ) && code != LOCK_UN)
568 code |= LOCK_NB; /* non-blocking, s.v.p. */
569 #if defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV)
570 code = HandleFlock(avc, code, &treq, clid, 0/*!onlymine*/);
572 #if defined(AFS_SGI_ENV)
573 AFS_RWLOCK((vnode_t *)avc, VRWLOCK_WRITE);
574 code = HandleFlock(avc, code, &treq, clid, 0/*!onlymine*/);
575 AFS_RWUNLOCK((vnode_t *)avc, VRWLOCK_WRITE);
577 code = HandleFlock(avc, code, &treq, 0, 0/*!onlymine*/);
580 code = afs_CheckCode(code, &treq, 3); /* defeat AIX -O bug */
588 * Get a description of the first lock which would
589 * block the lock specified. If the specified lock
590 * would succeed, fill in the lock structure with 'F_UNLCK'.
592 * To do that, we have to ask the server for the lock
594 * 1. The file is not locked by this machine.
595 * 2. Asking for write lock, and only the current
596 * PID has the file read locked.
598 #ifndef AFS_OSF_ENV /* getlock is a no-op for osf (for now) */
599 HandleGetLock(avc, af, areq, clid)
600 int clid; /* not used by some OSes */
601 register struct vcache *avc;
602 register struct vrequest *areq;
603 register struct AFS_FLOCK *af;
605 register afs_int32 code;
606 struct AFS_FLOCK flock;
608 lockIdSet(&flock, (struct SimpleLocks *)0, clid);
610 ObtainWriteLock(&avc->lock,122);
611 if (avc->flockCount == 0) {
612 /* We don't know ourselves, so ask the server. Unfortunately, we don't know the pid.
613 * Not even the server knows the pid. Besides, the process with the lock is on another machine
615 code = GetFlockCount(avc, areq);
616 if (code == 0 || (af->l_type == F_RDLCK && code > 0)) {
617 af->l_type = F_UNLCK;
621 af->l_type = F_RDLCK;
623 af->l_type = F_WRLCK;
626 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
632 if (af->l_type == F_RDLCK) {
634 * We want a read lock. If there are only
635 * read locks, or we are the one with the
636 * write lock, say it is unlocked.
638 if (avc->flockCount > 0 || /* only read locks */
639 !lockIdcmp2(&flock, avc, (struct SimpleLocks *)0, 1, clid)) {
640 af->l_type = F_UNLCK;
644 /* one write lock, but who? */
645 af->l_type = F_WRLCK; /* not us, so lock would block */
646 if (avc->slocks) { /* we know who, so tell */
647 af->l_pid = avc->slocks->pid;
648 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
649 af->l_sysid = avc->slocks->sysid;
652 af->l_pid = 0; /* XXX can't happen?? */
653 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
661 * Ok, we want a write lock. If there is a write lock
662 * already, and it is not this process, we fail.
664 if (avc->flockCount < 0) {
665 if (lockIdcmp2(&flock, avc, (struct SimpleLocks *)0, 1, clid)) {
666 af->l_type = F_WRLCK;
668 af->l_pid = avc->slocks->pid;
669 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
670 af->l_sysid = avc->slocks->sysid;
673 af->l_pid = 0; /* XXX can't happen?? */
674 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
680 /* we are the one with the write lock */
681 af->l_type = F_UNLCK;
686 * Want a write lock, and we know there are read locks.
687 * If there is more than one, or it isn't us, we cannot lock.
689 if ((avc->flockCount > 1)
690 || lockIdcmp2(&flock, avc, (struct SimpleLocks *)0, 1, clid)) {
691 struct SimpleLocks *slp;
693 af->l_type = F_RDLCK;
695 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
698 /* find a pid that isn't our own */
699 for (slp = avc->slocks; slp; slp = slp->next) {
700 if (lockIdcmp2(&flock, (struct vcache *)0, slp, 1, clid)) {
701 af->l_pid = slp->pid;
702 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
703 af->l_sysid = avc->slocks->sysid;
712 * Ok, we want a write lock. If there is a write lock
713 * already, and it is not this process, we fail.
715 if (avc->flockCount < 0) {
716 if (lockIdcmp2(&flock, avc, (struct SimpleLocks *)0, 1, clid)) {
717 af->l_type = F_WRLCK;
719 af->l_pid = avc->slocks->pid;
720 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
721 af->l_sysid = avc->slocks->sysid;
724 af->l_pid = 0; /* XXX can't happen?? */
725 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
731 /* we are the one with the write lock */
732 af->l_type = F_UNLCK;
737 * Want a write lock, and we know there are read locks.
738 * If there is more than one, or it isn't us, we cannot lock.
740 if ((avc->flockCount > 1)
741 || lockIdcmp2(&flock, avc, (struct SimpleLocks *)0, 1, clid)) {
742 struct SimpleLocks *slp;
743 af->l_type = F_RDLCK;
745 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
748 /* find a pid that isn't our own */
749 for (slp = avc->slocks; slp; slp = slp->next) {
750 if (lockIdcmp2(&flock, (struct vcache *)0, slp, 1, clid)) {
751 af->l_pid = slp->pid;
752 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
753 af->l_sysid = avc->slocks->sysid;
762 * Want a write lock, and there is just one read lock, and it
763 * is this process with a read lock. Ask the server if there
764 * are any more processes with the file locked.
766 code = GetFlockCount(avc, areq);
767 if (code == 0 || code == 1) {
768 af->l_type = F_UNLCK;
772 af->l_type = F_RDLCK;
774 af->l_type = F_WRLCK;
776 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
783 af->l_len = 0; /* to end of file */
786 ReleaseWriteLock(&avc->lock);
790 /* Get the 'flock' count from the server. This comes back in a 'spare'
791 * field from a GetStatus RPC. If we have any problems with the RPC,
792 * we lie and say the file is unlocked. If we ask any 'old' fileservers,
793 * the spare field will be a zero, saying the file is unlocked. This is
794 * OK, as a further 'lock' request will do the right thing.
796 static int GetFlockCount(struct vcache *avc, struct vrequest *areq)
798 register struct conn *tc;
799 register afs_int32 code;
800 struct AFSFetchStatus OutStatus;
801 struct AFSCallBack CallBack;
802 struct AFSVolSync tsync;
806 temp = areq->flags & O_NONBLOCK;
807 areq->flags |= O_NONBLOCK;
810 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
812 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHSTATUS);
813 #ifdef RX_ENABLE_LOCKS
815 #endif /* RX_ENABLE_LOCKS */
816 code = RXAFS_FetchStatus(tc->id, (struct AFSFid *) &avc->fid.Fid,
817 &OutStatus, &CallBack, &tsync);
818 #ifdef RX_ENABLE_LOCKS
820 #endif /* RX_ENABLE_LOCKS */
824 (afs_Analyze(tc, code, &avc->fid, areq,
825 AFS_STATS_FS_RPCIDX_FETCHSTATUS,
826 SHARED_LOCK, (struct cell *)0));
829 areq->flags &= ~O_NONBLOCK;
832 return(0); /* failed, say it is 'unlocked' */
834 return((int)OutStatus.spare2);
840 #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)
841 /* Flock not support on System V systems */
843 extern struct fileops afs_fileops;
844 afs_xflock (p, args, retval)
849 #else /* AFS_OSF_ENV */
858 struct vrequest treq;
862 AFS_STATCNT(afs_xflock);
865 uap = (struct a *)args;
866 getf(&fd, uap->fd, FILE_FLAGS_NULL, &u.u_file_state);
867 #else /* AFS_OSF_ENV */
868 #if defined(AFS_FBSD_ENV)
869 uap = (struct a *)u.u_ap;
871 uap = (struct a *)u.u_ap;
872 #endif /* AFS_FBSD_ENV */
877 if (flockDone = afs_InitReq(&treq, u.u_cred)) return flockDone;
878 /* first determine whether this is any sort of vnode */
879 if (fd->f_type == DTYPE_VNODE) {
880 /* good, this is a vnode; next see if it is an AFS vnode */
881 tvc = (struct vcache *) fd->f_data; /* valid, given a vnode */
882 if (IsAfsVnode((struct vnode *)tvc)) {
883 /* This is an AFS vnode, so do the work */
885 /* find real vcache entry; shouldn't be null if gnode ref count
888 tvc = (struct vcache *) afs_gntovn(tvc);
894 if ((fd->f_flag & (FEXLOCK | FSHLOCK)) && !(uap->com & LOCK_UN)) {
895 /* First, if fd already has lock, release it for relock path */
896 #if defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV) || (defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV))
897 HandleFlock(tvc, LOCK_UN, &treq, u.u_procp->p_pid, 0/*!onlymine*/);
899 HandleFlock(tvc, LOCK_UN, &treq, 0, 0/*!onlymine*/);
901 fd->f_flag &= ~(FEXLOCK | FSHLOCK);
903 /* now try the requested operation */
905 #if defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV) || (defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV))
906 code = HandleFlock(tvc, uap->com, &treq,
907 u.u_procp->p_pid, 0/*!onlymine*/);
909 code = HandleFlock(tvc, uap->com, &treq, 0, 0/*!onlymine*/);
915 if (uap->com & LOCK_UN) {
917 fd->f_flag &= ~(FEXLOCK | FSHLOCK);
922 #else /* AFS_OSF_ENV */
925 if (uap->com & LOCK_SH) fd->f_flag |= FSHLOCK;
926 else if (uap->com & LOCK_EX) fd->f_flag |= FEXLOCK;
930 fd->f_ops = &afs_fileops;
935 code = flock(p, args, retval);
942 #else /* AFS_OSF_ENV */
945 (*afs_longcall_procs.LC_flock)();
952 #endif /* !defined(AFS_AIX_ENV) && !defined(AFS_HPUX_ENV) && !defined(AFS_SUN5_ENV) && !defined(UKERNEL) && !defined(AFS_LINUX20_ENV) */