no-copy-libafs-builds-20021015
[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 "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 osi_VM_GetDownD(struct vcache *avc, struct dcache *adc)
46 {
47     int code;
48
49     AFS_GUNLOCK();
50     code = afs_putpage(AFSTOV(avc),
51                        (offset_t) AFS_CHUNKTOBASE(adc->f.chunk),
52                        AFS_CHUNKTOSIZE(adc->f.chunk),
53                        B_INVAL, CRED());
54     AFS_GLOCK();
55
56     return code;
57 }
58
59 /* Try to discard pages, in order to recycle a vcache entry.
60  *
61  * We also make some sanity checks:  ref count, open count, held locks.
62  *
63  * We also do some non-VM-related chores, such as releasing the cred pointer
64  * (for AIX and Solaris) and releasing the gnode (for AIX).
65  *
66  * Locking:  afs_xvcache lock is held.  If it is dropped and re-acquired,
67  *   *slept should be set to warn the caller.
68  *
69  * Formerly, afs_xvcache was dropped and re-acquired for Solaris, but now it
70  * is not dropped and re-acquired for any platform.  It may be that *slept is
71  * therefore obsolescent.
72  */
73 int osi_VM_FlushVCache(struct vcache *avc, int *slept)
74 {
75     if (avc->vrefCount != 0)
76         return EBUSY;
77
78     if (avc->opens)
79         return EBUSY;
80
81     /* if a lock is held, give up */
82     if (CheckLock(&avc->lock))
83         return EBUSY;
84     if (afs_CheckBozonLock(&avc->pvnLock))
85         return EBUSY;
86
87     AFS_GUNLOCK();
88     pvn_vplist_dirty(AFSTOV(avc), 0, NULL, B_TRUNC|B_INVAL, CRED());
89     AFS_GLOCK();
90
91     /* Might as well make the obvious check */
92     if (AFSTOV(avc)->v_pages)
93         return EBUSY;   /* should be all gone still */
94
95     rw_destroy(&avc->rwlock);
96     if (avc->credp) {
97         crfree(avc->credp);
98         avc->credp = NULL;
99     }
100
101
102     return 0;
103 }
104
105 /* Try to store pages to cache, in order to store a file back to the server.
106  *
107  * Locking:  the vcache entry's lock is held.  It will usually be dropped and
108  * re-obtained.
109  */
110 void osi_VM_StoreAllSegments(struct vcache *avc)
111 {
112     AFS_GUNLOCK();
113 #if     defined(AFS_SUN56_ENV)
114     (void) pvn_vplist_dirty(AFSTOV(avc), (u_offset_t)0, afs_putapage,
115                             0, CRED());
116 #else
117     (void) pvn_vplist_dirty(AFSTOV(avc), 0, afs_putapage, 0, CRED());
118 #endif
119     AFS_GLOCK();
120 }
121
122 /* Try to invalidate pages, for "fs flush" or "fs flushv"; or
123  * try to free pages, when deleting a file.
124  *
125  * Locking:  the vcache entry's lock is held.  It may be dropped and
126  * re-obtained.
127  */
128 void osi_VM_TryToSmush(struct vcache *avc, struct AFS_UCRED *acred, int sync)
129 {
130     AFS_GUNLOCK();
131 #if     defined(AFS_SUN56_ENV)
132     (void) pvn_vplist_dirty(AFSTOV(avc), (u_offset_t)0, afs_putapage,
133                             (sync ? B_INVAL : B_FREE), acred);
134 #else
135     (void) pvn_vplist_dirty(AFSTOV(avc), 0, afs_putapage,
136                             (sync ? B_INVAL : B_FREE), acred);
137 #endif
138     AFS_GLOCK();
139 }
140
141 /* Purge VM for a file when its callback is revoked.
142  *
143  * Locking:  No lock is held, not even the global lock.
144  */
145 void osi_VM_FlushPages(struct vcache *avc, struct AFS_UCRED *credp)
146 {
147     extern int afs_pvn_vptrunc;
148
149     afs_pvn_vptrunc++;
150     (void) afs_putpage(AFSTOV(avc), (offset_t)0, 0,
151                         B_TRUNC|B_INVAL, credp);
152 }
153
154 /* Zero no-longer-used part of last page, when truncating a file
155  *
156  * This function only exists for Solaris.  Other platforms do not support it.
157  *
158  * Locking:  the vcache entry lock is held.  It is released and re-obtained.
159  * The caller will raise activeV (to prevent pageins), but this function must
160  * be called first, since it causes a pagein.
161  */
162 void osi_VM_PreTruncate(struct vcache *avc, int alen, struct AFS_UCRED *acred)
163 {
164     page_t *pp;
165     int pageOffset = (alen & PAGEOFFSET);
166
167     if (pageOffset == 0) {
168         return;
169     }
170
171     ReleaseWriteLock(&avc->lock);
172     AFS_GUNLOCK();
173     pp = page_lookup(AFSTOV(avc), alen - pageOffset, SE_EXCL);
174     if (pp) {
175         pagezero(pp, pageOffset, PAGESIZE - pageOffset);
176         page_unlock(pp);
177     }
178     AFS_GLOCK();
179     ObtainWriteLock(&avc->lock,563);
180 }
181
182 /* Purge pages beyond end-of-file, when truncating a file.
183  *
184  * Locking:  no lock is held, not even the global lock.
185  * Pageins are blocked (activeV is raised).
186  */
187 void osi_VM_Truncate(struct vcache *avc, int alen, struct AFS_UCRED *acred)
188 {
189     /*
190      * It's OK to specify afs_putapage here, even though we aren't holding
191      * the vcache entry lock, because it isn't going to get called.
192      */
193     pvn_vplist_dirty(AFSTOV(avc), alen, afs_putapage, B_TRUNC|B_INVAL,
194                      acred);
195 }
196
197 #endif /* SUN5 && !NCR */