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"
19 #if !defined(AFS_HPUX_ENV) && !defined(AFS_SGI_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN80_ENV)
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"
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)
33 int afs_ustrategy(struct buf *abp)
38 struct iovec tiovec[1];
39 struct vcache *tvc = VTOAFS(abp->b_vp);
40 afs_int32 len = abp->b_bcount;
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;
49 AFS_STATCNT(afs_ustrategy);
52 * So that it won't change while reading it
54 ObtainReadLock(&tvc->lock);
61 ReleaseReadLock(&tvc->lock);
65 if (abp->b_iocmd == BIO_READ) {
67 if ((abp->b_flags & B_READ) == B_READ) {
69 /* read b_bcount bytes into kernel address b_un.b_addr starting
70 * at byte DEV_BSIZE * b_blkno. Bzero anything we can't read,
71 * and finally call iodone(abp). File is in abp->b_vp. Credentials
74 tuio.afsio_iov = tiovec;
75 tuio.afsio_iovcnt = 1;
76 #if defined(AFS_SUN5_ENV) || defined(AFS_XBSD_ENV)
77 # ifdef AFS_64BIT_CLIENT
79 tuio.afsio_offset = (afs_offs_t) ldbtob(abp->b_lblkno);
81 tuio.afsio_offset = (afs_offs_t) dbtob(abp->b_blkno);
83 # else /* AFS_64BIT_CLIENT */
84 tuio.afsio_offset = (u_int) dbtob(abp->b_blkno);
85 # endif /* AFS_64BIT_CLIENT */
87 tuio.afsio_offset = DEV_BSIZE * abp->b_blkno;
89 #if defined(AFS_NBSD40_ENV)
90 UIO_SETUP_SYSSPACE(&tuio);
92 tuio.afsio_seg = AFS_UIOSYS;
97 tuio.afsio_resid = abp->b_bcount;
98 #if defined(AFS_NBSD40_ENV)
99 tiovec[0].iov_base = abp->b_data;
100 #elif defined(AFS_XBSD_ENV)
101 tiovec[0].iov_base = abp->b_saveaddr;
103 tiovec[0].iov_base = abp->b_un.b_addr;
104 #endif /* AFS_XBSD_ENV */
105 tiovec[0].iov_len = abp->b_bcount;
106 /* are user's credentials valid here? probably, but this
107 * sure seems like the wrong things to do. */
108 #if defined(AFS_SUN5_ENV)
109 code = afs_nlrdwr(VTOAFS(abp->b_vp), &tuio, UIO_READ, 0, credp);
111 code = afs_rdwr(VTOAFS(abp->b_vp), &tuio, UIO_READ, 0, credp);
114 if (tuio.afsio_resid > 0)
115 #if defined(AFS_NBSD40_ENV)
116 memset((char *)abp->b_data + (uintptr_t)abp->b_bcount - tuio.afsio_resid, 0,
118 #elif defined(AFS_XBSD_ENV)
119 memset(abp->b_saveaddr + abp->b_bcount - tuio.afsio_resid, 0,
122 memset(abp->b_un.b_addr + abp->b_bcount - tuio.afsio_resid, 0,
124 #endif /* AFS_XBSD_ENV */
127 * If we read a block that is past EOF and the user was not storing
128 * to it, go ahead and write protect the page. This way we will detect
129 * storing beyond EOF in the future
131 if (dbtob(abp->b_blkno) + abp->b_bcount > tvc->f.m.Length) {
132 if ((abp->b_flags & B_PFSTORE) == 0) {
134 vm_protectp(tvc->segid, dbtob(abp->b_blkno) / PAGESIZE,
135 abp->b_bcount / PAGESIZE, RDONLY);
142 tuio.afsio_iov = tiovec;
143 tuio.afsio_iovcnt = 1;
144 #if defined(AFS_SUN5_ENV)
145 #ifdef AFS_64BIT_CLIENT
147 tuio.afsio_offset = (afs_offs_t) ldbtob(abp->b_lblkno);
149 tuio.afsio_offset = (afs_offs_t) dbtob(abp->b_blkno);
151 #else /* AFS_64BIT_CLIENT */
152 tuio.afsio_offset = (u_int) dbtob(abp->b_blkno);
153 #endif /* AFS_64BIT_CLIENT */
156 tuio.uio_limit = curproc->p_fsz_ctl.rlim_cur;
158 tuio.uio_limit = u.u_rlimit[RLIMIT_FSIZE].rlim_cur;
162 tuio.afsio_offset = DEV_BSIZE * abp->b_blkno;
164 #if defined(AFS_NBSD40_ENV)
165 UIO_SETUP_SYSSPACE(&tuio);
167 tuio.afsio_seg = AFS_UIOSYS;
170 tuio.afsio_fmode = 0;
174 * XXX It this really right? Ideally we should always write block size multiple
175 * and not any arbitrary size, right? XXX
177 len = MIN(len, tvc->f.m.Length - dbtob(abp->b_blkno));
179 tuio.afsio_resid = len;
180 #if defined(AFS_NBSD40_ENV)
181 tiovec[0].iov_base = abp->b_data;
182 #elif defined(AFS_XBSD_ENV)
183 tiovec[0].iov_base = abp->b_saveaddr;
185 tiovec[0].iov_base = abp->b_un.b_addr;
186 #endif /* AFS_XBSD_ENV */
187 tiovec[0].iov_len = len;
188 /* are user's credentials valid here? probably, but this
189 * sure seems like the wrong things to do. */
190 #if defined(AFS_SUN5_ENV)
191 code = afs_nlrdwr(VTOAFS(abp->b_vp), &tuio, UIO_WRITE, 0, credp);
193 code = afs_rdwr(VTOAFS(abp->b_vp), &tuio, UIO_WRITE, 0, credp);
197 #if defined (AFS_XBSD_ENV)
200 #if !defined(AFS_FBSD_ENV) && !defined(AFS_NBSD50_ENV)
201 abp->b_flags |= B_ERROR;
206 #if defined(AFS_AIX32_ENV)
208 #elif defined(AFS_FBSD60_ENV)
209 (*abp->b_iodone)(abp);
210 #elif defined(AFS_FBSD_ENV)
212 #elif defined(AFS_NBSD40_ENV)
213 abp->b_resid = tuio.uio_resid;
215 #elif defined(AFS_XBSD_ENV)
217 #elif !defined(AFS_SUN5_ENV)
221 afs_Trace3(afs_iclSetp, CM_TRACE_STRATEGYDONE, ICL_TYPE_POINTER, tvc,
222 ICL_TYPE_INT32, code, ICL_TYPE_LONG, tuio.afsio_resid);
226 #endif /* !AFS_HPUX_ENV && !AFS_SGI_ENV && !AFS_LINUX20_ENV */