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