aix-51-support-20030701
[openafs.git] / src / afs / VNOPS / afs_vnop_strategy.c
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 RCSID("$Header$");
19
20 #if !defined(AFS_HPUX_ENV) && !defined(AFS_SGI_ENV) && !defined(AFS_LINUX20_ENV)
21
22 #include "afs/sysincludes.h"    /* Standard vendor system headers */
23 #include "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"
28
29
30
31 int
32 #if     defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
33 afs_ustrategy(abp, credp)
34     struct AFS_UCRED *credp;
35 #else
36 afs_ustrategy(abp)
37 #endif
38     register struct buf *abp; {
39     register afs_int32 code;
40     struct uio tuio;
41     register struct vcache *tvc = VTOAFS(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_XBSD_ENV)
44 #ifdef  AFS_AIX41_ENV
45     struct ucred *credp;
46 #else
47     struct AFS_UCRED *credp = u.u_cred;
48 #endif
49 #endif
50     struct iovec tiovec[1];
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_FBSD50_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_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_XBSD_ENV)
80 #ifdef AFS_64BIT_CLIENT
81         tuio.afsio_offset = (afs_offs_t) dbtob(abp->b_blkno);
82 #else /* AFS_64BIT_CLIENT */
83         tuio.afsio_offset = (u_int) dbtob(abp->b_blkno);
84 #if     defined(AFS_SUN5_ENV)
85         tuio._uio_offset._p._u = 0;
86 #endif
87 #endif /* AFS_64BIT_CLIENT */
88 #else
89         tuio.afsio_offset = DEV_BSIZE * abp->b_blkno;
90 #endif
91         tuio.afsio_seg = AFS_UIOSYS;
92 #ifdef AFS_UIOFMODE
93         tuio.afsio_fmode = 0;
94 #endif
95         tuio.afsio_resid = abp->b_bcount;
96 #if defined(AFS_XBSD_ENV)
97         tiovec[0].iov_base = abp->b_saveaddr;
98 #else
99         tiovec[0].iov_base = abp->b_un.b_addr;
100 #endif /* AFS_XBSD_ENV */
101         tiovec[0].iov_len = abp->b_bcount;
102         /* are user's credentials valid here?  probably, but this
103              sure seems like the wrong things to do. */
104 #if     defined(AFS_SUN5_ENV)
105         code = afs_nlrdwr(VTOAFS(abp->b_vp), &tuio, UIO_READ, 0, credp);
106 #else
107         code = afs_rdwr(VTOAFS(abp->b_vp), &tuio, UIO_READ, 0, credp);
108 #endif
109         if (code == 0) {
110             if (tuio.afsio_resid > 0)
111 #if defined(AFS_XBSD_ENV)
112                 memset(abp->b_saveaddr + abp->b_bcount - tuio.afsio_resid, 0, tuio.afsio_resid);
113 #else
114                 memset(abp->b_un.b_addr + abp->b_bcount - tuio.afsio_resid, 0, tuio.afsio_resid);
115 #endif /* AFS_XBSD_ENV */
116 #ifdef  AFS_AIX32_ENV
117             /*
118              * If we read a block that is past EOF and the user was not storing
119              * to it, go ahead and write protect the page. This way we will detect
120              * storing beyond EOF in the future
121              */
122             if (dbtob(abp->b_blkno) + abp->b_bcount > tvc->m.Length) {
123                 if ((abp->b_flags & B_PFSTORE) == 0) {
124                     AFS_GUNLOCK();
125                     vm_protectp(tvc->segid, dbtob(abp->b_blkno)/PAGESIZE,
126                                 abp->b_bcount/PAGESIZE, RDONLY);
127                     AFS_GLOCK();
128                 }
129             }
130 #endif
131         }
132     }
133     else {
134         tuio.afsio_iov = tiovec;
135         tuio.afsio_iovcnt = 1;
136 #if     defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
137 #ifdef AFS_64BIT_CLIENT
138         tuio.afsio_offset = (afs_offs_t) dbtob(abp->b_blkno);
139 #else /* AFS_64BIT_CLIENT */
140         tuio.afsio_offset = (u_int) dbtob(abp->b_blkno);
141 #ifdef  AFS_SUN5_ENV
142         tuio._uio_offset._p._u = 0;
143 #endif
144 #endif /* AFS_64BIT_CLIENT */
145 #ifdef  AFS_SUN5_ENV
146 #ifdef  AFS_SUN59_ENV
147         tuio.uio_limit = curproc->p_fsz_ctl.rlim_cur;
148 #else
149         tuio.uio_limit = u.u_rlimit[RLIMIT_FSIZE].rlim_cur;
150 #endif
151 #endif
152 #else
153         tuio.afsio_offset = DEV_BSIZE * abp->b_blkno;
154 #endif
155         tuio.afsio_seg = AFS_UIOSYS;
156 #ifdef AFS_UIOFMODE
157         tuio.afsio_fmode = 0;
158 #endif
159 #ifdef  AFS_AIX32_ENV   
160         /*
161          * XXX It this really right? Ideally we should always write block size multiple
162          * and not any arbitrary size, right? XXX
163          */
164         len = MIN(len, tvc->m.Length - dbtob(abp->b_blkno));
165 #endif
166 #ifdef AFS_ALPHA_ENV
167         len = MIN(abp->b_bcount, (VTOAFS(abp->b_vp))->m.Length - dbtob(abp->b_blkno));
168 #endif  /* AFS_ALPHA_ENV */
169         tuio.afsio_resid = len;
170 #if defined(AFS_XBSD_ENV)
171         tiovec[0].iov_base = abp->b_saveaddr;
172 #else
173         tiovec[0].iov_base = abp->b_un.b_addr;
174 #endif /* AFS_XBSD_ENV */
175         tiovec[0].iov_len = len;
176         /* are user's credentials valid here?  probably, but this
177              sure seems like the wrong things to do. */
178 #if     defined(AFS_SUN5_ENV)
179         code = afs_nlrdwr(VTOAFS(abp->b_vp), &tuio, UIO_WRITE, 0, credp);
180 #else
181         code = afs_rdwr(VTOAFS(abp->b_vp), &tuio, UIO_WRITE, 0, credp);
182 #endif
183     }
184 #if     !defined(AFS_AIX32_ENV) && !defined(AFS_SUN5_ENV)
185 #if defined(AFS_DUX40_ENV) || (defined (AFS_XBSD_ENV) && !defined (AFS_FBSD50_ENV))
186     if (code) {
187         abp->b_error = code;
188         abp->b_flags |= B_ERROR;
189     }
190     biodone(abp);
191 #if defined(AFS_DUX40_ENV)
192     if (code && !(abp->b_flags & B_READ)) {
193         /* prevent ubc from retrying writes */
194         AFS_GUNLOCK();
195         ubc_invalidate(AFSTOV(tvc)->v_object,
196                        (vm_offset_t)dbtob(abp->b_blkno),
197                        PAGE_SIZE, B_INVAL);
198         AFS_GLOCK();
199     }
200 #endif
201 #else  /* AFS_DUX40_ENV */
202     iodone(abp);
203 #endif /* AFS_DUX40_ENV */
204 #endif
205 #ifdef  AFS_AIX32_ENV
206     crfree(credp);
207 #endif
208     afs_Trace3(afs_iclSetp, CM_TRACE_STRATEGYDONE, ICL_TYPE_POINTER, tvc,
209                ICL_TYPE_INT32, code,
210                ICL_TYPE_LONG, tuio.afsio_resid);
211     return code;
212 }
213
214 #endif /* !AFS_HPUX_ENV  && !AFS_SGI_ENV && !AFS_LINUX20_ENV */