bc0ff13d804cb7ec88bcae4c990892a90f811284
[openafs.git] / src / afs / AIX / osi_vm.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
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
8  */
9
10 #include <afsconfig.h>
11 #include "afs/param.h"
12
13 RCSID
14     ("$Header$");
15
16 #include "afs/sysincludes.h"    /* Standard vendor system headers */
17 #include "afsincludes.h"        /* Afs-based standard headers */
18 #include "afs/afs_stats.h"      /* statistics */
19
20 /* Try to discard pages, in order to recycle a vcache entry.
21  *
22  * We also make some sanity checks:  ref count, open count, held locks.
23  *
24  * We also do some non-VM-related chores, such as releasing the cred pointer
25  * (for AIX and Solaris) and releasing the gnode (for AIX).
26  *
27  * Locking:  afs_xvcache lock is held.  If it is dropped and re-acquired,
28  *   *slept should be set to warn the caller.
29  *
30  * Formerly, afs_xvcache was dropped and re-acquired for Solaris, but now it
31  * is not dropped and re-acquired for any platform.  It may be that *slept is
32  * therefore obsolescent.
33  */
34 int
35 osi_VM_FlushVCache(struct vcache *avc, int *slept)
36 {
37     if (avc->vrefCount != 0)
38         return EBUSY;
39
40     if (avc->opens)
41         return EBUSY;
42
43     /* Just in case someone is still referring to the vnode we
44      * give up trying to get rid of this guy */
45     if (avc->vrefCount || CheckLock(&avc->lock) || LockWaiters(&avc->lock))
46         return EBUSY;
47
48     if (avc->segid) {
49         AFS_GUNLOCK();
50         vms_delete(avc->segid);
51         AFS_GLOCK();
52         avc->segid = avc->vmh = NULL;
53     }
54
55     if (avc->credp) {
56         crfree(avc->credp);
57         avc->credp = NULL;
58     }
59
60     /* Free the alloced gnode that was accompanying the vcache's vnode */
61     aix_gnode_rele(AFSTOV(avc));
62
63     return 0;
64 }
65
66 /* Try to store pages to cache, in order to store a file back to the server.
67  *
68  * Locking:  the vcache entry's lock is held.  It will usually be dropped and
69  * re-obtained.
70  */
71 void
72 osi_VM_StoreAllSegments(struct vcache *avc)
73 {
74     if (avc->segid) {
75         /*
76          * The execsOrWriters test is done so that we don't thrash on
77          * the vm_writep call below. We only initiate a pageout of the
78          * dirty vm pages on the last store...
79          * this is strictly a pragmatic decision, and _does_ break the 
80          * advertised AFS consistency semantics.  Without this hack,
81          * AIX systems panic under heavy load.  I consider the current
82          * behavior a bug introduced to hack around a worse bug. XXX
83          *
84          * Removed do_writep governing sync'ing behavior.
85          */
86         ReleaseWriteLock(&avc->lock);   /* XXX */
87         AFS_GUNLOCK();
88         vm_writep(avc->segid, 0, MAXFSIZE / PAGESIZE - 1);
89         vms_iowait(avc->segid);
90         AFS_GLOCK();
91         ObtainWriteLock(&avc->lock, 93);        /* XXX */
92         /*
93          * The following is necessary because of the following
94          * asynchronicity: We open a file, write to it and 
95          * close the file
96          * if CCore flag is set, we clear it and do the extra
97          * decrement ourselves now.
98          * If we're called by the CCore clearer, the CCore flag
99          * will already be clear, so we don't have to worry about
100          * clearing it twice.
101          * avc was "VN_HELD" and "crheld" when CCore was set in
102          * afs_FakeClose
103          */
104         if (avc->f.states & CCore) {
105             avc->f.states &= ~CCore;
106             avc->opens--;
107             avc->execsOrWriters--;
108             AFS_RELE(AFSTOV(avc));
109             crfree((struct ucred *)avc->linkData);
110             avc->linkData = NULL;
111         }
112     }
113 }
114
115 /* Try to invalidate pages, for "fs flush" or "fs flushv"; or
116  * try to free pages, when deleting a file.
117  *
118  * Locking:  the vcache entry's lock is held.  It may be dropped and 
119  * re-obtained.
120  *
121  * Since we drop and re-obtain the lock, we can't guarantee that there won't
122  * be some pages around when we return, newly created by concurrent activity.
123  */
124 void
125 osi_VM_TryToSmush(struct vcache *avc, struct AFS_UCRED *acred, int sync)
126 {
127     if (avc->segid) {
128         ReleaseWriteLock(&avc->lock);
129         AFS_GUNLOCK();
130         vm_flushp(avc->segid, 0, MAXFSIZE / PAGESIZE - 1);
131         vms_iowait(avc->segid); /* XXX Wait?? XXX */
132         AFS_GLOCK();
133         ObtainWriteLock(&avc->lock, 60);
134     }
135 }
136
137 /* Purge VM for a file when its callback is revoked.
138  *
139  * Locking:  No lock is held, not even the global lock.
140  */
141 void
142 osi_VM_FlushPages(struct vcache *avc, struct AFS_UCRED *credp)
143 {
144     if (avc->segid) {
145         vm_flushp(avc->segid, 0, MAXFSIZE / PAGESIZE - 1);
146         /*
147          * XXX We probably don't need to wait but better be safe XXX
148          */
149         vms_iowait(avc->segid);
150     }
151 }
152
153 /* Purge pages beyond end-of-file, when truncating a file.
154  *
155  * Locking:  no lock is held, not even the global lock.
156  * activeV is raised.  This is supposed to block pageins, but at present
157  * it only works on Solaris.
158  */
159 void
160 osi_VM_Truncate(struct vcache *avc, int alen, struct AFS_UCRED *acred)
161 {
162     if (avc->segid) {
163         int firstpage = (alen + PAGESIZE - 1) / PAGESIZE;
164         vm_releasep(avc->segid, firstpage, MAXFSIZE / PAGESIZE - firstpage);
165         vms_iowait(avc->segid); /* Do we need this? */
166     }
167 }