discon-allow-saving-vcaches-on-shutdown-20090126
[openafs.git] / src / afs / VNOPS / afs_vnop_strategy.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 /*
11  * Implements:
12  * afs_ustrategy
13  */
14
15 #include <afsconfig.h>
16 #include "afs/param.h"
17
18 RCSID
19     ("$Header$");
20
21 #if !defined(AFS_HPUX_ENV) && !defined(AFS_SGI_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN80_ENV)
22
23 #include "afs/sysincludes.h"    /* Standard vendor system headers */
24 #include "afsincludes.h"        /* Afs-based standard headers */
25 #include "afs/afs_stats.h"      /* statistics */
26 #include "afs/afs_cbqueue.h"
27 #include "afs/nfsclient.h"
28 #include "afs/afs_osidnlc.h"
29
30
31
32 #if     defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
33 int afs_ustrategy(register struct buf *abp, struct AFS_UCRED *credp)
34 #else
35 int afs_ustrategy(register struct buf *abp)
36 #endif
37 {
38     register afs_int32 code;
39     struct uio tuio;
40     struct uio *tuiop = &tuio;
41     struct iovec tiovec[1];
42     register struct vcache *tvc = VTOAFS(abp->b_vp);
43     register afs_int32 len = abp->b_bcount;
44 #if     !defined(AFS_SUN5_ENV) && !defined(AFS_OSF_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_XBSD_ENV)
45 #ifdef  AFS_AIX41_ENV
46     struct ucred *credp;
47 #else
48     struct AFS_UCRED *credp = u.u_cred;
49 #endif
50 #endif
51
52     AFS_STATCNT(afs_ustrategy);
53 #ifdef  AFS_AIX41_ENV
54     /*
55      * So that it won't change while reading it
56      */
57     ObtainReadLock(&tvc->lock);
58     if (tvc->credp) {
59         credp = tvc->credp;
60         crhold(credp);
61     } else {
62         credp = crref();
63     }
64     ReleaseReadLock(&tvc->lock);
65     osi_Assert(credp);
66 #endif
67 #ifdef AFS_FBSD50_ENV
68     if (abp->b_iocmd == BIO_READ) {
69 #else
70     if ((abp->b_flags & B_READ) == B_READ) {
71 #endif
72         /* read b_bcount bytes into kernel address b_un.b_addr starting
73          * at byte DEV_BSIZE * b_blkno.  Bzero anything we can't read,
74          * and finally call iodone(abp).  File is in abp->b_vp.  Credentials
75          * are from u area??
76          */
77         tuio.afsio_iov = tiovec;
78         tuio.afsio_iovcnt = 1;
79 #if     defined(AFS_OSF_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_XBSD_ENV)
80 #ifdef AFS_64BIT_CLIENT
81 #ifdef AFS_SUN5_ENV
82         tuio.afsio_offset = (afs_offs_t) ldbtob(abp->b_lblkno);
83 #else
84         tuio.afsio_offset = (afs_offs_t) dbtob(abp->b_blkno);
85 #endif
86 #else /* AFS_64BIT_CLIENT */
87         tuio.afsio_offset = (u_int) dbtob(abp->b_blkno);
88 #endif /* AFS_64BIT_CLIENT */
89 #else
90         tuio.afsio_offset = DEV_BSIZE * abp->b_blkno;
91 #endif
92         tuio.afsio_seg = AFS_UIOSYS;
93 #ifdef AFS_UIOFMODE
94         tuio.afsio_fmode = 0;
95 #endif
96         tuio.afsio_resid = abp->b_bcount;
97 #if defined(AFS_XBSD_ENV)
98         tiovec[0].iov_base = abp->b_saveaddr;
99 #else
100         tiovec[0].iov_base = abp->b_un.b_addr;
101 #endif /* AFS_XBSD_ENV */
102         tiovec[0].iov_len = abp->b_bcount;
103         /* are user's credentials valid here?  probably, but this
104          * sure seems like the wrong things to do. */
105 #if     defined(AFS_SUN5_ENV)
106         code = afs_nlrdwr(VTOAFS(abp->b_vp), &tuio, UIO_READ, 0, credp);
107 #else
108         code = afs_rdwr(VTOAFS(abp->b_vp), &tuio, UIO_READ, 0, credp);
109 #endif
110         if (code == 0) {
111             if (tuio.afsio_resid > 0)
112 #if defined(AFS_XBSD_ENV)
113                 memset(abp->b_saveaddr + abp->b_bcount - tuio.afsio_resid, 0,
114                        tuio.afsio_resid);
115 #else
116                 memset(abp->b_un.b_addr + abp->b_bcount - tuio.afsio_resid, 0,
117                        tuio.afsio_resid);
118 #endif /* AFS_XBSD_ENV */
119 #ifdef  AFS_AIX32_ENV
120             /*
121              * If we read a block that is past EOF and the user was not storing
122              * to it, go ahead and write protect the page. This way we will detect
123              * storing beyond EOF in the future
124              */
125             if (dbtob(abp->b_blkno) + abp->b_bcount > tvc->f.m.Length) {
126                 if ((abp->b_flags & B_PFSTORE) == 0) {
127                     AFS_GUNLOCK();
128                     vm_protectp(tvc->segid, dbtob(abp->b_blkno) / PAGESIZE,
129                                 abp->b_bcount / PAGESIZE, RDONLY);
130                     AFS_GLOCK();
131                 }
132             }
133 #endif
134         }
135     } else {
136         tuio.afsio_iov = tiovec;
137         tuio.afsio_iovcnt = 1;
138 #if     defined(AFS_OSF_ENV) || defined(AFS_SUN5_ENV)
139 #ifdef AFS_64BIT_CLIENT
140 #ifdef AFS_SUN5_ENV
141         tuio.afsio_offset = (afs_offs_t) ldbtob(abp->b_lblkno);
142 #else
143         tuio.afsio_offset = (afs_offs_t) dbtob(abp->b_blkno);
144 #endif
145 #else /* AFS_64BIT_CLIENT */
146         tuio.afsio_offset = (u_int) dbtob(abp->b_blkno);
147 #endif /* AFS_64BIT_CLIENT */
148 #ifdef  AFS_SUN5_ENV
149 #ifdef  AFS_SUN59_ENV
150         tuio.uio_limit = curproc->p_fsz_ctl.rlim_cur;
151 #else
152         tuio.uio_limit = u.u_rlimit[RLIMIT_FSIZE].rlim_cur;
153 #endif
154 #endif
155 #else
156         tuio.afsio_offset = DEV_BSIZE * abp->b_blkno;
157 #endif
158         tuio.afsio_seg = AFS_UIOSYS;
159 #ifdef AFS_UIOFMODE
160         tuio.afsio_fmode = 0;
161 #endif
162 #ifdef  AFS_AIX32_ENV
163         /*
164          * XXX It this really right? Ideally we should always write block size multiple
165          * and not any arbitrary size, right? XXX
166          */
167         len = MIN(len, tvc->f.m.Length - dbtob(abp->b_blkno));
168 #endif
169 #ifdef AFS_OSF_ENV
170         len =
171             MIN(abp->b_bcount,
172                 (VTOAFS(abp->b_vp))->f.m.Length - dbtob(abp->b_blkno));
173 #endif /* AFS_OSF_ENV */
174         tuio.afsio_resid = len;
175 #if defined(AFS_XBSD_ENV)
176         tiovec[0].iov_base = abp->b_saveaddr;
177 #else
178         tiovec[0].iov_base = abp->b_un.b_addr;
179 #endif /* AFS_XBSD_ENV */
180         tiovec[0].iov_len = len;
181         /* are user's credentials valid here?  probably, but this
182          * sure seems like the wrong things to do. */
183 #if     defined(AFS_SUN5_ENV)
184         code = afs_nlrdwr(VTOAFS(abp->b_vp), &tuio, UIO_WRITE, 0, credp);
185 #else
186         code = afs_rdwr(VTOAFS(abp->b_vp), &tuio, UIO_WRITE, 0, credp);
187 #endif
188     }
189
190 #if defined(AFS_DUX40_ENV) || defined (AFS_XBSD_ENV)
191     if (code) {
192         abp->b_error = code;
193 #if !defined(AFS_FBSD50_ENV)
194         abp->b_flags |= B_ERROR;
195 #endif
196     }
197 #endif
198
199 #if defined(AFS_AIX32_ENV)
200     crfree(credp);
201 #elif defined(AFS_DUX40_ENV)
202     biodone(abp);
203     if (code && !(abp->b_flags & B_READ)) {
204         /* prevent ubc from retrying writes */
205         AFS_GUNLOCK();
206         ubc_invalidate(AFSTOV(tvc)->v_object,
207                        (vm_offset_t) dbtob(abp->b_blkno), PAGE_SIZE, B_INVAL);
208         AFS_GLOCK();
209     }
210 #elif defined(AFS_FBSD60_ENV)
211     (*abp->b_iodone)(abp);
212 #elif defined(AFS_FBSD50_ENV)
213     biodone(&abp->b_io);
214 #elif defined(AFS_XBSD_ENV)
215     biodone(abp);
216 #elif !defined(AFS_SUN5_ENV)
217     iodone(abp);
218 #endif
219
220     afs_Trace3(afs_iclSetp, CM_TRACE_STRATEGYDONE, ICL_TYPE_POINTER, tvc,
221                ICL_TYPE_INT32, code, ICL_TYPE_LONG, tuio.afsio_resid);
222     return code;
223 }
224
225 #endif /* !AFS_HPUX_ENV  && !AFS_SGI_ENV && !AFS_LINUX20_ENV */