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 memset(&tuio
, 0, sizeof(tuio
));
50 memset(&tiovec
, 0, sizeof(tiovec
));
52 AFS_STATCNT(afs_ustrategy
);
55 * So that it won't change while reading it
57 ObtainReadLock(&tvc
->lock
);
64 ReleaseReadLock(&tvc
->lock
);
68 if (abp
->b_iocmd
== BIO_READ
) {
70 if ((abp
->b_flags
& B_READ
) == B_READ
) {
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
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
82 tuio
.afsio_offset
= (afs_offs_t
) ldbtob(abp
->b_lblkno
);
84 tuio
.afsio_offset
= (afs_offs_t
) dbtob(abp
->b_blkno
);
86 # else /* AFS_64BIT_CLIENT */
87 tuio
.afsio_offset
= (u_int
) dbtob(abp
->b_blkno
);
88 # endif /* AFS_64BIT_CLIENT */
90 tuio
.afsio_offset
= DEV_BSIZE
* abp
->b_blkno
;
92 #if defined(AFS_NBSD40_ENV)
93 UIO_SETUP_SYSSPACE(&tuio
);
95 tuio
.afsio_seg
= AFS_UIOSYS
;
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
;
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
);
114 code
= afs_rdwr(VTOAFS(abp
->b_vp
), &tuio
, UIO_READ
, 0, credp
);
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,
121 #elif defined(AFS_XBSD_ENV)
122 memset(abp
->b_saveaddr
+ abp
->b_bcount
- tuio
.afsio_resid
, 0,
125 memset(abp
->b_un
.b_addr
+ abp
->b_bcount
- tuio
.afsio_resid
, 0,
127 #endif /* AFS_XBSD_ENV */
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
134 if (dbtob(abp
->b_blkno
) + abp
->b_bcount
> tvc
->f
.m
.Length
) {
135 if ((abp
->b_flags
& B_PFSTORE
) == 0) {
137 vm_protectp(tvc
->segid
, dbtob(abp
->b_blkno
) / PAGESIZE
,
138 abp
->b_bcount
/ PAGESIZE
, RDONLY
);
145 tuio
.afsio_iov
= tiovec
;
146 tuio
.afsio_iovcnt
= 1;
147 #if defined(AFS_SUN5_ENV)
148 #ifdef AFS_64BIT_CLIENT
150 tuio
.afsio_offset
= (afs_offs_t
) ldbtob(abp
->b_lblkno
);
152 tuio
.afsio_offset
= (afs_offs_t
) dbtob(abp
->b_blkno
);
154 #else /* AFS_64BIT_CLIENT */
155 tuio
.afsio_offset
= (u_int
) dbtob(abp
->b_blkno
);
156 #endif /* AFS_64BIT_CLIENT */
159 tuio
.uio_limit
= curproc
->p_fsz_ctl
.rlim_cur
;
161 tuio
.uio_limit
= u
.u_rlimit
[RLIMIT_FSIZE
].rlim_cur
;
165 tuio
.afsio_offset
= DEV_BSIZE
* abp
->b_blkno
;
167 #if defined(AFS_NBSD40_ENV)
168 UIO_SETUP_SYSSPACE(&tuio
);
170 tuio
.afsio_seg
= AFS_UIOSYS
;
173 tuio
.afsio_fmode
= 0;
177 * XXX It this really right? Ideally we should always write block size multiple
178 * and not any arbitrary size, right? XXX
180 len
= MIN(len
, tvc
->f
.m
.Length
- dbtob(abp
->b_blkno
));
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
;
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
);
196 code
= afs_rdwr(VTOAFS(abp
->b_vp
), &tuio
, UIO_WRITE
, 0, credp
);
200 #if defined (AFS_XBSD_ENV)
203 #if !defined(AFS_FBSD_ENV) && !defined(AFS_NBSD50_ENV)
204 abp
->b_flags
|= B_ERROR
;
209 #if defined(AFS_AIX32_ENV)
211 #elif defined(AFS_FBSD60_ENV)
212 (*abp
->b_iodone
)(abp
);
213 #elif defined(AFS_FBSD_ENV)
215 #elif defined(AFS_NBSD40_ENV)
216 abp
->b_resid
= tuio
.uio_resid
;
218 #elif defined(AFS_XBSD_ENV)
220 #elif !defined(AFS_SUN5_ENV)
224 afs_Trace3(afs_iclSetp
, CM_TRACE_STRATEGYDONE
, ICL_TYPE_POINTER
, tvc
,
225 ICL_TYPE_INT32
, code
, ICL_TYPE_LONG
, tuio
.afsio_resid
);
229 #endif /* !AFS_HPUX_ENV && !AFS_SGI_ENV && !AFS_LINUX20_ENV */