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