Commit | Line | Data |
---|---|---|
805e021f CE |
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 | ||
19 | #if !defined(AFS_HPUX_ENV) && !defined(AFS_SGI_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN80_ENV) | |
20 | ||
21 | #include "afs/sysincludes.h" /* Standard vendor system headers */ | |
22 | #include "afsincludes.h" /* Afs-based standard headers */ | |
23 | #include "afs/afs_stats.h" /* statistics */ | |
24 | #include "afs/afs_cbqueue.h" | |
25 | #include "afs/nfsclient.h" | |
26 | #include "afs/afs_osidnlc.h" | |
27 | ||
28 | ||
29 | ||
30 | #if defined(AFS_SUN5_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV) | |
31 | int afs_ustrategy(struct buf *abp, afs_ucred_t *credp) | |
32 | #else | |
33 | int afs_ustrategy(struct buf *abp) | |
34 | #endif | |
35 | { | |
36 | afs_int32 code; | |
37 | struct uio tuio; | |
38 | struct iovec tiovec[1]; | |
39 | struct vcache *tvc = VTOAFS(abp->b_vp); | |
40 | afs_int32 len = abp->b_bcount; | |
41 | #ifdef AFS_AIX41_ENV | |
42 | struct ucred *credp; | |
43 | #elif defined(UKERNEL) | |
44 | afs_ucred_t *credp = get_user_struct()->u_cred; | |
45 | #elif !defined(AFS_SUN5_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_XBSD_ENV) | |
46 | afs_ucred_t *credp = u.u_cred; | |
47 | #endif | |
48 | ||
49 | memset(&tuio, 0, sizeof(tuio)); | |
50 | memset(&tiovec, 0, sizeof(tiovec)); | |
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_FBSD_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_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 | #if defined(AFS_NBSD40_ENV) | |
93 | UIO_SETUP_SYSSPACE(&tuio); | |
94 | #else | |
95 | tuio.afsio_seg = AFS_UIOSYS; | |
96 | #endif | |
97 | #ifdef AFS_UIOFMODE | |
98 | tuio.afsio_fmode = 0; | |
99 | #endif | |
100 | tuio.afsio_resid = abp->b_bcount; | |
101 | #if defined(AFS_NBSD40_ENV) || defined(FBSD_STRUCT_BUF_NO_SAVEADDR) | |
102 | tiovec[0].iov_base = abp->b_data; | |
103 | #elif defined(AFS_XBSD_ENV) | |
104 | tiovec[0].iov_base = abp->b_saveaddr; | |
105 | #else | |
106 | tiovec[0].iov_base = abp->b_un.b_addr; | |
107 | #endif /* AFS_XBSD_ENV */ | |
108 | tiovec[0].iov_len = abp->b_bcount; | |
109 | /* are user's credentials valid here? probably, but this | |
110 | * sure seems like the wrong things to do. */ | |
111 | #if defined(AFS_SUN5_ENV) | |
112 | code = afs_nlrdwr(VTOAFS(abp->b_vp), &tuio, UIO_READ, 0, credp); | |
113 | #else | |
114 | code = afs_rdwr(VTOAFS(abp->b_vp), &tuio, UIO_READ, 0, credp); | |
115 | #endif | |
116 | if (code == 0) { | |
117 | if (tuio.afsio_resid > 0) | |
118 | #if defined(AFS_NBSD40_ENV) || defined(FBSD_STRUCT_BUF_NO_SAVEADDR) | |
119 | memset((char *)abp->b_data + (uintptr_t)abp->b_bcount - tuio.afsio_resid, 0, | |
120 | tuio.afsio_resid); | |
121 | #elif defined(AFS_XBSD_ENV) | |
122 | memset(abp->b_saveaddr + abp->b_bcount - tuio.afsio_resid, 0, | |
123 | tuio.afsio_resid); | |
124 | #else | |
125 | memset(abp->b_un.b_addr + abp->b_bcount - tuio.afsio_resid, 0, | |
126 | tuio.afsio_resid); | |
127 | #endif /* AFS_XBSD_ENV */ | |
128 | #ifdef AFS_AIX32_ENV | |
129 | /* | |
130 | * If we read a block that is past EOF and the user was not storing | |
131 | * to it, go ahead and write protect the page. This way we will detect | |
132 | * storing beyond EOF in the future | |
133 | */ | |
134 | if (dbtob(abp->b_blkno) + abp->b_bcount > tvc->f.m.Length) { | |
135 | if ((abp->b_flags & B_PFSTORE) == 0) { | |
136 | AFS_GUNLOCK(); | |
137 | vm_protectp(tvc->segid, dbtob(abp->b_blkno) / PAGESIZE, | |
138 | abp->b_bcount / PAGESIZE, RDONLY); | |
139 | AFS_GLOCK(); | |
140 | } | |
141 | } | |
142 | #endif | |
143 | } | |
144 | } else { | |
145 | tuio.afsio_iov = tiovec; | |
146 | tuio.afsio_iovcnt = 1; | |
147 | #if defined(AFS_SUN5_ENV) | |
148 | #ifdef AFS_64BIT_CLIENT | |
149 | #ifdef AFS_SUN5_ENV | |
150 | tuio.afsio_offset = (afs_offs_t) ldbtob(abp->b_lblkno); | |
151 | #else | |
152 | tuio.afsio_offset = (afs_offs_t) dbtob(abp->b_blkno); | |
153 | #endif | |
154 | #else /* AFS_64BIT_CLIENT */ | |
155 | tuio.afsio_offset = (u_int) dbtob(abp->b_blkno); | |
156 | #endif /* AFS_64BIT_CLIENT */ | |
157 | #ifdef AFS_SUN5_ENV | |
158 | #ifdef AFS_SUN59_ENV | |
159 | tuio.uio_limit = curproc->p_fsz_ctl.rlim_cur; | |
160 | #else | |
161 | tuio.uio_limit = u.u_rlimit[RLIMIT_FSIZE].rlim_cur; | |
162 | #endif | |
163 | #endif | |
164 | #else | |
165 | tuio.afsio_offset = DEV_BSIZE * abp->b_blkno; | |
166 | #endif | |
167 | #if defined(AFS_NBSD40_ENV) | |
168 | UIO_SETUP_SYSSPACE(&tuio); | |
169 | #else | |
170 | tuio.afsio_seg = AFS_UIOSYS; | |
171 | #endif | |
172 | #ifdef AFS_UIOFMODE | |
173 | tuio.afsio_fmode = 0; | |
174 | #endif | |
175 | #ifdef AFS_AIX32_ENV | |
176 | /* | |
177 | * XXX It this really right? Ideally we should always write block size multiple | |
178 | * and not any arbitrary size, right? XXX | |
179 | */ | |
180 | len = MIN(len, tvc->f.m.Length - dbtob(abp->b_blkno)); | |
181 | #endif | |
182 | tuio.afsio_resid = len; | |
183 | #if defined(AFS_NBSD40_ENV) || defined(FBSD_STRUCT_BUF_NO_SAVEADDR) | |
184 | tiovec[0].iov_base = abp->b_data; | |
185 | #elif defined(AFS_XBSD_ENV) | |
186 | tiovec[0].iov_base = abp->b_saveaddr; | |
187 | #else | |
188 | tiovec[0].iov_base = abp->b_un.b_addr; | |
189 | #endif /* AFS_XBSD_ENV */ | |
190 | tiovec[0].iov_len = len; | |
191 | /* are user's credentials valid here? probably, but this | |
192 | * sure seems like the wrong things to do. */ | |
193 | #if defined(AFS_SUN5_ENV) | |
194 | code = afs_nlrdwr(VTOAFS(abp->b_vp), &tuio, UIO_WRITE, 0, credp); | |
195 | #else | |
196 | code = afs_rdwr(VTOAFS(abp->b_vp), &tuio, UIO_WRITE, 0, credp); | |
197 | #endif | |
198 | } | |
199 | ||
200 | #if defined (AFS_XBSD_ENV) | |
201 | if (code) { | |
202 | abp->b_error = code; | |
203 | #if !defined(AFS_FBSD_ENV) && !defined(AFS_NBSD50_ENV) | |
204 | abp->b_flags |= B_ERROR; | |
205 | #endif | |
206 | } | |
207 | #endif | |
208 | ||
209 | #if defined(AFS_AIX32_ENV) | |
210 | crfree(credp); | |
211 | #elif defined(AFS_FBSD60_ENV) | |
212 | (*abp->b_iodone)(abp); | |
213 | #elif defined(AFS_FBSD_ENV) | |
214 | biodone(&abp->b_io); | |
215 | #elif defined(AFS_NBSD40_ENV) | |
216 | abp->b_resid = tuio.uio_resid; | |
217 | biodone(abp); | |
218 | #elif defined(AFS_XBSD_ENV) | |
219 | biodone(abp); | |
220 | #elif !defined(AFS_SUN5_ENV) | |
221 | iodone(abp); | |
222 | #endif | |
223 | ||
224 | afs_Trace3(afs_iclSetp, CM_TRACE_STRATEGYDONE, ICL_TYPE_POINTER, tvc, | |
225 | ICL_TYPE_INT32, code, ICL_TYPE_LONG, tuio.afsio_resid); | |
226 | return code; | |
227 | } | |
228 | ||
229 | #endif /* !AFS_HPUX_ENV && !AFS_SGI_ENV && !AFS_LINUX20_ENV */ |