Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / afs / VNOPS / afs_vnop_strategy.c
CommitLineData
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)
31int afs_ustrategy(struct buf *abp, afs_ucred_t *credp)
32#else
33int 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 */