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"
20 #if !defined(AFS_HPUX_ENV) && !defined(AFS_SGI_ENV) && !defined(AFS_LINUX20_ENV)
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"
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;
38 register struct buf *abp; {
39 register afs_int32 code;
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)
47 struct AFS_UCRED *credp = u.u_cred;
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;
53 struct iovec tiovec[1];
55 AFS_STATCNT(afs_ustrategy);
58 * So that it won't change while reading it
60 ObtainReadLock(&tvc->lock);
67 ReleaseReadLock(&tvc->lock);
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
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;
86 #endif /* AFS_64BIT_CLIENT */
88 tuio.afsio_offset = DEV_BSIZE * abp->b_blkno;
90 tuio.afsio_seg = AFS_UIOSYS;
94 tuio.afsio_resid = abp->b_bcount;
95 #if defined(AFS_FBSD_ENV)
96 tiovec[0].iov_base = abp->b_saveaddr;
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);
106 code = afs_rdwr((struct vcache *) abp->b_vp, &tuio, UIO_READ, 0, credp);
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);
113 memset(abp->b_un.b_addr + abp->b_bcount - tuio.afsio_resid, 0, tuio.afsio_resid);
114 #endif /* AFS_FBSD_ENV */
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
121 if (dbtob(abp->b_blkno) + abp->b_bcount > tvc->m.Length) {
122 if ((abp->b_flags & B_PFSTORE) == 0) {
124 vm_protectp(tvc->vmh, dbtob(abp->b_blkno)/PAGESIZE,
125 abp->b_bcount/PAGESIZE, RDONLY);
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);
141 tuio._uio_offset._p._u = 0;
143 #endif /* AFS_64BIT_CLIENT */
146 tuio.uio_limit = curproc->p_fsz_ctl.rlim_cur;
148 tuio.uio_limit = u.u_rlimit[RLIMIT_FSIZE].rlim_cur;
152 tuio.afsio_offset = DEV_BSIZE * abp->b_blkno;
154 tuio.afsio_seg = AFS_UIOSYS;
156 tuio.afsio_fmode = 0;
160 * XXX It this really right? Ideally we should always write block size multiple
161 * and not any arbitrary size, right? XXX
163 len = MIN(len, tvc->m.Length - dbtob(abp->b_blkno));
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;
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);
180 code = afs_rdwr((struct vcache *) abp->b_vp, &tuio, UIO_WRITE, 0, credp);
183 #if !defined(AFS_AIX32_ENV) && !defined(AFS_SUN5_ENV)
184 #if defined(AFS_DUX40_ENV) || defined (AFS_FBSD_ENV)
187 abp->b_flags |= B_ERROR;
190 #if defined(AFS_DUX40_ENV)
191 if (code && !(abp->b_flags & B_READ)) {
192 /* prevent ubc from retrying writes */
194 ubc_invalidate(((struct vnode *)tvc)->v_object,
195 (vm_offset_t)dbtob(abp->b_blkno),
200 #else /* AFS_DUX40_ENV */
202 #endif /* AFS_DUX40_ENV */
207 afs_Trace3(afs_iclSetp, CM_TRACE_STRATEGYDONE, ICL_TYPE_POINTER, tvc,
208 ICL_TYPE_INT32, code,
209 ICL_TYPE_LONG, tuio.afsio_resid);
213 #endif /* !AFS_HPUX_ENV && !AFS_SGI_ENV && !AFS_LINUX20_ENV */