2 * Copyright 2000, International Business Machines Corporation and others.
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
15 #include <afsconfig.h>
16 #include "afs/param.h"
21 #if !defined(AFS_HPUX_ENV) && !defined(AFS_SGI_ENV) && !defined(AFS_LINUX20_ENV)
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"
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;
39 register struct buf *abp;
41 register afs_int32 code;
43 register struct vcache *tvc = VTOAFS(abp->b_vp);
44 register afs_int32 len = abp->b_bcount;
45 #if !defined(AFS_SUN5_ENV) && !defined(AFS_OSF_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_XBSD_ENV)
49 struct AFS_UCRED *credp = u.u_cred;
52 struct iovec tiovec[1];
54 AFS_STATCNT(afs_ustrategy);
57 * So that it won't change while reading it
59 ObtainReadLock(&tvc->lock);
66 ReleaseReadLock(&tvc->lock);
70 if (abp->b_iocmd == BIO_READ) {
72 if ((abp->b_flags & B_READ) == B_READ) {
74 /* read b_bcount bytes into kernel address b_un.b_addr starting
75 * at byte DEV_BSIZE * b_blkno. Bzero anything we can't read,
76 * and finally call iodone(abp). File is in abp->b_vp. Credentials
79 tuio.afsio_iov = tiovec;
80 tuio.afsio_iovcnt = 1;
81 #if defined(AFS_OSF_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_XBSD_ENV)
82 #ifdef AFS_64BIT_CLIENT
84 tuio.afsio_offset = (afs_offs_t) ldbtob(abp->b_lblkno);
86 tuio.afsio_offset = (afs_offs_t) dbtob(abp->b_blkno);
88 #else /* AFS_64BIT_CLIENT */
89 tuio.afsio_offset = (u_int) dbtob(abp->b_blkno);
90 #endif /* AFS_64BIT_CLIENT */
92 tuio.afsio_offset = DEV_BSIZE * abp->b_blkno;
94 tuio.afsio_seg = AFS_UIOSYS;
98 tuio.afsio_resid = abp->b_bcount;
99 #if defined(AFS_XBSD_ENV)
100 tiovec[0].iov_base = abp->b_saveaddr;
102 tiovec[0].iov_base = abp->b_un.b_addr;
103 #endif /* AFS_XBSD_ENV */
104 tiovec[0].iov_len = abp->b_bcount;
105 /* are user's credentials valid here? probably, but this
106 * sure seems like the wrong things to do. */
107 #if defined(AFS_SUN5_ENV)
108 code = afs_nlrdwr(VTOAFS(abp->b_vp), &tuio, UIO_READ, 0, credp);
110 code = afs_rdwr(VTOAFS(abp->b_vp), &tuio, UIO_READ, 0, credp);
113 if (tuio.afsio_resid > 0)
114 #if defined(AFS_XBSD_ENV)
115 memset(abp->b_saveaddr + abp->b_bcount - tuio.afsio_resid, 0,
118 memset(abp->b_un.b_addr + abp->b_bcount - tuio.afsio_resid, 0,
120 #endif /* AFS_XBSD_ENV */
123 * If we read a block that is past EOF and the user was not storing
124 * to it, go ahead and write protect the page. This way we will detect
125 * storing beyond EOF in the future
127 if (dbtob(abp->b_blkno) + abp->b_bcount > tvc->m.Length) {
128 if ((abp->b_flags & B_PFSTORE) == 0) {
130 vm_protectp(tvc->segid, dbtob(abp->b_blkno) / PAGESIZE,
131 abp->b_bcount / PAGESIZE, RDONLY);
138 tuio.afsio_iov = tiovec;
139 tuio.afsio_iovcnt = 1;
140 #if defined(AFS_OSF_ENV) || defined(AFS_SUN5_ENV)
141 #ifdef AFS_64BIT_CLIENT
143 tuio.afsio_offset = (afs_offs_t) ldbtob(abp->b_lblkno);
145 tuio.afsio_offset = (afs_offs_t) dbtob(abp->b_blkno);
147 #else /* AFS_64BIT_CLIENT */
148 tuio.afsio_offset = (u_int) dbtob(abp->b_blkno);
149 #endif /* AFS_64BIT_CLIENT */
152 tuio.uio_limit = curproc->p_fsz_ctl.rlim_cur;
154 tuio.uio_limit = u.u_rlimit[RLIMIT_FSIZE].rlim_cur;
158 tuio.afsio_offset = DEV_BSIZE * abp->b_blkno;
160 tuio.afsio_seg = AFS_UIOSYS;
162 tuio.afsio_fmode = 0;
166 * XXX It this really right? Ideally we should always write block size multiple
167 * and not any arbitrary size, right? XXX
169 len = MIN(len, tvc->m.Length - dbtob(abp->b_blkno));
174 (VTOAFS(abp->b_vp))->m.Length - dbtob(abp->b_blkno));
175 #endif /* AFS_OSF_ENV */
176 tuio.afsio_resid = len;
177 #if defined(AFS_XBSD_ENV)
178 tiovec[0].iov_base = abp->b_saveaddr;
180 tiovec[0].iov_base = abp->b_un.b_addr;
181 #endif /* AFS_XBSD_ENV */
182 tiovec[0].iov_len = len;
183 /* are user's credentials valid here? probably, but this
184 * sure seems like the wrong things to do. */
185 #if defined(AFS_SUN5_ENV)
186 code = afs_nlrdwr(VTOAFS(abp->b_vp), &tuio, UIO_WRITE, 0, credp);
188 code = afs_rdwr(VTOAFS(abp->b_vp), &tuio, UIO_WRITE, 0, credp);
192 #if defined(AFS_DUX40_ENV) || defined (AFS_XBSD_ENV)
195 #if !defined(AFS_FBSD50_ENV)
196 abp->b_flags |= B_ERROR;
201 #if defined(AFS_AIX32_ENV)
203 #elif defined(AFS_DUX40_ENV)
205 if (code && !(abp->b_flags & B_READ)) {
206 /* prevent ubc from retrying writes */
208 ubc_invalidate(AFSTOV(tvc)->v_object,
209 (vm_offset_t) dbtob(abp->b_blkno), PAGE_SIZE, B_INVAL);
212 #elif defined(AFS_FBSD60_ENV)
213 (*abp->b_iodone)(abp);
214 #elif defined(AFS_FBSD50_ENV)
216 #elif defined(AFS_XBSD_ENV)
218 #elif !defined(AFS_SUN5_ENV)
222 afs_Trace3(afs_iclSetp, CM_TRACE_STRATEGYDONE, ICL_TYPE_POINTER, tvc,
223 ICL_TYPE_INT32, code, ICL_TYPE_LONG, tuio.afsio_resid);
227 #endif /* !AFS_HPUX_ENV && !AFS_SGI_ENV && !AFS_LINUX20_ENV */