2e610d568fcf4fa37dea9a2a8ec875299bbf15e4
[openafs.git] / src / afs / SOLARIS / 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("$Header$");
14
15 #include "../afs/sysincludes.h" /* Standard vendor system headers */
16 #include "../afs/afsincludes.h" /* Afs-based standard headers */
17 #include "../afs/afs_stats.h"  /* statistics */
18 #include "../afs/nfsclient.h"  
19
20 #if     defined(AFS_SUN5_ENV)
21 /* This file contains Solaris VM-related code for the cache manager. */
22
23 #include <sys/mman.h>
24 #include <vm/hat.h>
25 #include <vm/as.h>
26 #include <vm/page.h>
27 #include <vm/pvn.h>
28 #include <vm/seg.h>
29 #include <vm/seg_map.h>
30 #include <vm/seg_vn.h>
31 #include <vm/rm.h>
32 #include <sys/modctl.h>
33 #include <sys/syscall.h>
34 #include <sys/debug.h>
35 #include <sys/fs_subr.h>
36
37 /* Try to invalidate pages, in order to recycle a dcache entry.
38  *
39  * This function only exists for Solaris.  For other platforms, it's OK to
40  * recycle a dcache entry without invalidating pages, because the strategy
41  * function can call afs_GetDCache().
42  *
43  * Locking:  only the global lock is held on entry.
44  */
45 int
46 osi_VM_GetDownD(avc, adc)
47     struct vcache *avc;
48     struct dcache *adc;
49 {
50     int code;
51
52     AFS_GUNLOCK();
53     code = afs_putpage(AFSTOV(avc),
54                        (offset_t) AFS_CHUNKTOBASE(adc->f.chunk),
55                        AFS_CHUNKTOSIZE(adc->f.chunk),
56                        B_INVAL, CRED());
57     AFS_GLOCK();
58
59     return code;
60 }
61
62 /* Try to discard pages, in order to recycle a vcache entry.
63  *
64  * We also make some sanity checks:  ref count, open count, held locks.
65  *
66  * We also do some non-VM-related chores, such as releasing the cred pointer
67  * (for AIX and Solaris) and releasing the gnode (for AIX).
68  *
69  * Locking:  afs_xvcache lock is held.  If it is dropped and re-acquired,
70  *   *slept should be set to warn the caller.
71  *
72  * Formerly, afs_xvcache was dropped and re-acquired for Solaris, but now it
73  * is not dropped and re-acquired for any platform.  It may be that *slept is
74  * therefore obsolescent.
75  */
76 int
77 osi_VM_FlushVCache(avc, slept)
78     struct vcache *avc;
79     int *slept;
80 {
81     if (avc->vrefCount != 0)
82         return EBUSY;
83
84     if (avc->opens)
85         return EBUSY;
86
87     /* if a lock is held, give up */
88     if (CheckLock(&avc->lock))
89         return EBUSY;
90     if (afs_CheckBozonLock(&avc->pvnLock))
91         return EBUSY;
92
93     AFS_GUNLOCK();
94     pvn_vplist_dirty(AFSTOV(avc), 0, NULL, B_TRUNC|B_INVAL, CRED());
95     AFS_GLOCK();
96
97     /* Might as well make the obvious check */
98     if (AFSTOV(avc)->v_pages)
99         return EBUSY;   /* should be all gone still */
100
101     rw_destroy(&avc->rwlock);
102     if (avc->credp) {
103         crfree(avc->credp);
104         avc->credp = NULL;
105     }
106
107
108     return 0;
109 }
110
111 /* Try to store pages to cache, in order to store a file back to the server.
112  *
113  * Locking:  the vcache entry's lock is held.  It will usually be dropped and
114  * re-obtained.
115  */
116 void
117 osi_VM_StoreAllSegments(avc)
118     struct vcache *avc;
119 {
120     AFS_GUNLOCK();
121 #if     defined(AFS_SUN56_ENV)
122     (void) pvn_vplist_dirty(AFSTOV(avc), (u_offset_t)0, afs_putapage,
123                             0, CRED());
124 #else
125     (void) pvn_vplist_dirty(AFSTOV(avc), 0, afs_putapage, 0, CRED());
126 #endif
127     AFS_GLOCK();
128 }
129
130 /* Try to invalidate pages, for "fs flush" or "fs flushv"; or
131  * try to free pages, when deleting a file.
132  *
133  * Locking:  the vcache entry's lock is held.  It may be dropped and
134  * re-obtained.
135  */
136 void
137 osi_VM_TryToSmush(avc, acred, sync)
138     struct vcache *avc;
139     struct AFS_UCRED *acred;
140     int sync;
141 {
142     AFS_GUNLOCK();
143 #if     defined(AFS_SUN56_ENV)
144     (void) pvn_vplist_dirty(AFSTOV(avc), (u_offset_t)0, afs_putapage,
145                             (sync ? B_INVAL : B_FREE), acred);
146 #else
147     (void) pvn_vplist_dirty(AFSTOV(avc), 0, afs_putapage,
148                             (sync ? B_INVAL : B_FREE), acred);
149 #endif
150     AFS_GLOCK();
151 }
152
153 /* Purge VM for a file when its callback is revoked.
154  *
155  * Locking:  No lock is held, not even the global lock.
156  */
157 void
158 osi_VM_FlushPages(avc, credp)
159     struct vcache *avc;
160     struct AFS_UCRED *credp;
161 {
162     extern int afs_pvn_vptrunc;
163
164     afs_pvn_vptrunc++;
165     (void) afs_putpage(AFSTOV(avc), (offset_t)0, 0,
166                         B_TRUNC|B_INVAL, credp);
167 }
168
169 /* Zero no-longer-used part of last page, when truncating a file
170  *
171  * This function only exists for Solaris.  Other platforms do not support it.
172  *
173  * Locking:  the vcache entry lock is held.  It is released and re-obtained.
174  * The caller will raise activeV (to prevent pageins), but this function must
175  * be called first, since it causes a pagein.
176  */
177 void
178 osi_VM_PreTruncate(avc, alen, acred)
179     struct vcache *avc;
180     int alen;
181     struct AFS_UCRED *acred;
182 {
183     page_t *pp;
184     int pageOffset = (alen & PAGEOFFSET);
185
186     if (pageOffset == 0) {
187         return;
188     }
189
190     ReleaseWriteLock(&avc->lock);
191     AFS_GUNLOCK();
192     pp = page_lookup(AFSTOV(avc), alen - pageOffset, SE_EXCL);
193     if (pp) {
194         pagezero(pp, pageOffset, PAGESIZE - pageOffset);
195         page_unlock(pp);
196     }
197     AFS_GLOCK();
198     ObtainWriteLock(&avc->lock,563);
199 }
200
201 /* Purge pages beyond end-of-file, when truncating a file.
202  *
203  * Locking:  no lock is held, not even the global lock.
204  * Pageins are blocked (activeV is raised).
205  */
206 void
207 osi_VM_Truncate(avc, alen, acred)
208     struct vcache *avc;
209     int alen;
210     struct AFS_UCRED *acred;
211 {
212     /*
213      * It's OK to specify afs_putapage here, even though we aren't holding
214      * the vcache entry lock, because it isn't going to get called.
215      */
216     pvn_vplist_dirty(AFSTOV(avc), alen, afs_putapage, B_TRUNC|B_INVAL,
217                      acred);
218 }
219
220 #endif /* SUN5 && !NCR */