openbsd-20021014
[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_XBSD_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 = VTOAFS(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_XBSD_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     struct iovec tiovec[1];
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     if ((abp->b_flags & B_READ) == B_READ) {
68         /* read b_bcount bytes into kernel address b_un.b_addr starting
69             at byte DEV_BSIZE * b_blkno.  Bzero anything we can't read,
70             and finally call iodone(abp).  File is in abp->b_vp.  Credentials
71             are from u area??
72         */
73         tuio.afsio_iov = tiovec;
74         tuio.afsio_iovcnt = 1;
75 #if     defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_XBSD_ENV)
76 #ifdef AFS_64BIT_CLIENT
77         tuio.afsio_offset = (afs_offs_t) dbtob(abp->b_blkno);
78 #else /* AFS_64BIT_CLIENT */
79         tuio.afsio_offset = (u_int) dbtob(abp->b_blkno);
80 #if     defined(AFS_SUN5_ENV)
81         tuio._uio_offset._p._u = 0;
82 #endif
83 #endif /* AFS_64BIT_CLIENT */
84 #else
85         tuio.afsio_offset = DEV_BSIZE * abp->b_blkno;
86 #endif
87         tuio.afsio_seg = AFS_UIOSYS;
88 #ifdef AFS_UIOFMODE
89         tuio.afsio_fmode = 0;
90 #endif
91         tuio.afsio_resid = abp->b_bcount;
92 #if defined(AFS_XBSD_ENV)
93         tiovec[0].iov_base = abp->b_saveaddr;
94 #else
95         tiovec[0].iov_base = abp->b_un.b_addr;
96 #endif /* AFS_XBSD_ENV */
97         tiovec[0].iov_len = abp->b_bcount;
98         /* are user's credentials valid here?  probably, but this
99              sure seems like the wrong things to do. */
100 #if     defined(AFS_SUN5_ENV)
101         code = afs_nlrdwr(VTOAFS(abp->b_vp), &tuio, UIO_READ, 0, credp);
102 #else
103         code = afs_rdwr(VTOAFS(abp->b_vp), &tuio, UIO_READ, 0, credp);
104 #endif
105         if (code == 0) {
106             if (tuio.afsio_resid > 0)
107 #if defined(AFS_XBSD_ENV)
108                 memset(abp->b_saveaddr + abp->b_bcount - tuio.afsio_resid, 0, tuio.afsio_resid);
109 #else
110                 memset(abp->b_un.b_addr + abp->b_bcount - tuio.afsio_resid, 0, tuio.afsio_resid);
111 #endif /* AFS_XBSD_ENV */
112 #ifdef  AFS_AIX32_ENV
113             /*
114              * If we read a block that is past EOF and the user was not storing
115              * to it, go ahead and write protect the page. This way we will detect
116              * storing beyond EOF in the future
117              */
118             if (dbtob(abp->b_blkno) + abp->b_bcount > tvc->m.Length) {
119                 if ((abp->b_flags & B_PFSTORE) == 0) {
120                     AFS_GUNLOCK();
121                     vm_protectp(tvc->vmh, dbtob(abp->b_blkno)/PAGESIZE,
122                                 abp->b_bcount/PAGESIZE, RDONLY);
123                     AFS_GLOCK();
124                 }
125             }
126 #endif
127         }
128     }
129     else {
130         tuio.afsio_iov = tiovec;
131         tuio.afsio_iovcnt = 1;
132 #if     defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
133 #ifdef AFS_64BIT_CLIENT
134         tuio.afsio_offset = (afs_offs_t) dbtob(abp->b_blkno);
135 #else /* AFS_64BIT_CLIENT */
136         tuio.afsio_offset = (u_int) dbtob(abp->b_blkno);
137 #ifdef  AFS_SUN5_ENV
138         tuio._uio_offset._p._u = 0;
139 #endif
140 #endif /* AFS_64BIT_CLIENT */
141 #ifdef  AFS_SUN5_ENV
142 #ifdef  AFS_SUN59_ENV
143         tuio.uio_limit = curproc->p_fsz_ctl.rlim_cur;
144 #else
145         tuio.uio_limit = u.u_rlimit[RLIMIT_FSIZE].rlim_cur;
146 #endif
147 #endif
148 #else
149         tuio.afsio_offset = DEV_BSIZE * abp->b_blkno;
150 #endif
151         tuio.afsio_seg = AFS_UIOSYS;
152 #ifdef AFS_UIOFMODE
153         tuio.afsio_fmode = 0;
154 #endif
155 #ifdef  AFS_AIX32_ENV   
156         /*
157          * XXX It this really right? Ideally we should always write block size multiple
158          * and not any arbitrary size, right? XXX
159          */
160         len = MIN(len, tvc->m.Length - dbtob(abp->b_blkno));
161 #endif
162 #ifdef AFS_ALPHA_ENV
163         len = MIN(abp->b_bcount, (VTOAFS(abp->b_vp))->m.Length - dbtob(abp->b_blkno));
164 #endif  /* AFS_ALPHA_ENV */
165         tuio.afsio_resid = len;
166 #if defined(AFS_XBSD_ENV)
167         tiovec[0].iov_base = abp->b_saveaddr;
168 #else
169         tiovec[0].iov_base = abp->b_un.b_addr;
170 #endif /* AFS_XBSD_ENV */
171         tiovec[0].iov_len = len;
172         /* are user's credentials valid here?  probably, but this
173              sure seems like the wrong things to do. */
174 #if     defined(AFS_SUN5_ENV)
175         code = afs_nlrdwr(VTOAFS(abp->b_vp), &tuio, UIO_WRITE, 0, credp);
176 #else
177         code = afs_rdwr(VTOAFS(abp->b_vp), &tuio, UIO_WRITE, 0, credp);
178 #endif
179     }
180 #if     !defined(AFS_AIX32_ENV) && !defined(AFS_SUN5_ENV)
181 #if defined(AFS_DUX40_ENV) || defined (AFS_XBSD_ENV)
182     if (code) {
183         abp->b_error = code;
184         abp->b_flags |= B_ERROR;
185     }
186     biodone(abp);
187 #if defined(AFS_DUX40_ENV)
188     if (code && !(abp->b_flags & B_READ)) {
189         /* prevent ubc from retrying writes */
190         AFS_GUNLOCK();
191         ubc_invalidate(AFSTOV(tvc)->v_object,
192                        (vm_offset_t)dbtob(abp->b_blkno),
193                        PAGE_SIZE, B_INVAL);
194         AFS_GLOCK();
195     }
196 #endif
197 #else  /* AFS_DUX40_ENV */
198     iodone(abp);
199 #endif /* AFS_DUX40_ENV */
200 #endif
201 #ifdef  AFS_AIX32_ENV
202     crfree(credp);
203 #endif
204     afs_Trace3(afs_iclSetp, CM_TRACE_STRATEGYDONE, ICL_TYPE_POINTER, tvc,
205                ICL_TYPE_INT32, code,
206                ICL_TYPE_LONG, tuio.afsio_resid);
207     return code;
208 }
209
210 #endif /* !AFS_HPUX_ENV  && !AFS_SGI_ENV && !AFS_LINUX20_ENV */