solars-sparc32-largefile-20051011
[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
19     ("$Header$");
20
21 #if !defined(AFS_HPUX_ENV) && !defined(AFS_SGI_ENV) && !defined(AFS_LINUX20_ENV)
22
23 #include "afs/sysincludes.h"    /* Standard vendor system headers */
24 #include "afsincludes.h"        /* Afs-based standard headers */
25 #include "afs/afs_stats.h"      /* statistics */
26 #include "afs/afs_cbqueue.h"
27 #include "afs/nfsclient.h"
28 #include "afs/afs_osidnlc.h"
29
30
31
32 int
33 #if     defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
34 afs_ustrategy(abp, credp)
35      struct AFS_UCRED *credp;
36 #else
37 afs_ustrategy(abp)
38 #endif
39      register struct buf *abp;
40 {
41     register afs_int32 code;
42     struct uio tuio;
43     register struct vcache *tvc = VTOAFS(abp->b_vp);
44     register afs_int32 len = abp->b_bcount;
45 #if     !defined(AFS_SUN5_ENV) && !defined(AFS_OSF_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_XBSD_ENV)
46 #ifdef  AFS_AIX41_ENV
47     struct ucred *credp;
48 #else
49     struct AFS_UCRED *credp = u.u_cred;
50 #endif
51 #endif
52     struct iovec tiovec[1];
53
54     AFS_STATCNT(afs_ustrategy);
55 #ifdef  AFS_AIX41_ENV
56     /*
57      * So that it won't change while reading it
58      */
59     ObtainReadLock(&tvc->lock);
60     if (tvc->credp) {
61         credp = tvc->credp;
62         crhold(credp);
63     } else {
64         credp = crref();
65     }
66     ReleaseReadLock(&tvc->lock);
67     osi_Assert(credp);
68 #endif
69 #ifdef AFS_FBSD50_ENV
70     if (abp->b_iocmd == BIO_READ) {
71 #else
72     if ((abp->b_flags & B_READ) == B_READ) {
73 #endif
74         /* read b_bcount bytes into kernel address b_un.b_addr starting
75          * at byte DEV_BSIZE * b_blkno.  Bzero anything we can't read,
76          * and finally call iodone(abp).  File is in abp->b_vp.  Credentials
77          * are from u area??
78          */
79         tuio.afsio_iov = tiovec;
80         tuio.afsio_iovcnt = 1;
81 #if     defined(AFS_OSF_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_XBSD_ENV)
82 #ifdef AFS_64BIT_CLIENT
83 #ifdef AFS_SUN5_ENV
84         tuio.afsio_offset = (afs_offs_t) ldbtob(abp->b_lblkno);
85 #else
86         tuio.afsio_offset = (afs_offs_t) dbtob(abp->b_blkno);
87 #endif
88 #else /* AFS_64BIT_CLIENT */
89         tuio.afsio_offset = (u_int) dbtob(abp->b_blkno);
90 #endif /* AFS_64BIT_CLIENT */
91 #else
92         tuio.afsio_offset = DEV_BSIZE * abp->b_blkno;
93 #endif
94         tuio.afsio_seg = AFS_UIOSYS;
95 #ifdef AFS_UIOFMODE
96         tuio.afsio_fmode = 0;
97 #endif
98         tuio.afsio_resid = abp->b_bcount;
99 #if defined(AFS_XBSD_ENV)
100         tiovec[0].iov_base = abp->b_saveaddr;
101 #else
102         tiovec[0].iov_base = abp->b_un.b_addr;
103 #endif /* AFS_XBSD_ENV */
104         tiovec[0].iov_len = abp->b_bcount;
105         /* are user's credentials valid here?  probably, but this
106          * sure seems like the wrong things to do. */
107 #if     defined(AFS_SUN5_ENV)
108         code = afs_nlrdwr(VTOAFS(abp->b_vp), &tuio, UIO_READ, 0, credp);
109 #else
110         code = afs_rdwr(VTOAFS(abp->b_vp), &tuio, UIO_READ, 0, credp);
111 #endif
112         if (code == 0) {
113             if (tuio.afsio_resid > 0)
114 #if defined(AFS_XBSD_ENV)
115                 memset(abp->b_saveaddr + abp->b_bcount - tuio.afsio_resid, 0,
116                        tuio.afsio_resid);
117 #else
118                 memset(abp->b_un.b_addr + abp->b_bcount - tuio.afsio_resid, 0,
119                        tuio.afsio_resid);
120 #endif /* AFS_XBSD_ENV */
121 #ifdef  AFS_AIX32_ENV
122             /*
123              * If we read a block that is past EOF and the user was not storing
124              * to it, go ahead and write protect the page. This way we will detect
125              * storing beyond EOF in the future
126              */
127             if (dbtob(abp->b_blkno) + abp->b_bcount > tvc->m.Length) {
128                 if ((abp->b_flags & B_PFSTORE) == 0) {
129                     AFS_GUNLOCK();
130                     vm_protectp(tvc->segid, dbtob(abp->b_blkno) / PAGESIZE,
131                                 abp->b_bcount / PAGESIZE, RDONLY);
132                     AFS_GLOCK();
133                 }
134             }
135 #endif
136         }
137     } else {
138         tuio.afsio_iov = tiovec;
139         tuio.afsio_iovcnt = 1;
140 #if     defined(AFS_OSF_ENV) || defined(AFS_SUN5_ENV)
141 #ifdef AFS_64BIT_CLIENT
142 #ifdef AFS_SUN5_ENV
143         tuio.afsio_offset = (afs_offs_t) ldbtob(abp->b_lblkno);
144 #else
145         tuio.afsio_offset = (afs_offs_t) dbtob(abp->b_blkno);
146 #endif
147 #else /* AFS_64BIT_CLIENT */
148         tuio.afsio_offset = (u_int) dbtob(abp->b_blkno);
149 #endif /* AFS_64BIT_CLIENT */
150 #ifdef  AFS_SUN5_ENV
151 #ifdef  AFS_SUN59_ENV
152         tuio.uio_limit = curproc->p_fsz_ctl.rlim_cur;
153 #else
154         tuio.uio_limit = u.u_rlimit[RLIMIT_FSIZE].rlim_cur;
155 #endif
156 #endif
157 #else
158         tuio.afsio_offset = DEV_BSIZE * abp->b_blkno;
159 #endif
160         tuio.afsio_seg = AFS_UIOSYS;
161 #ifdef AFS_UIOFMODE
162         tuio.afsio_fmode = 0;
163 #endif
164 #ifdef  AFS_AIX32_ENV
165         /*
166          * XXX It this really right? Ideally we should always write block size multiple
167          * and not any arbitrary size, right? XXX
168          */
169         len = MIN(len, tvc->m.Length - dbtob(abp->b_blkno));
170 #endif
171 #ifdef AFS_OSF_ENV
172         len =
173             MIN(abp->b_bcount,
174                 (VTOAFS(abp->b_vp))->m.Length - dbtob(abp->b_blkno));
175 #endif /* AFS_OSF_ENV */
176         tuio.afsio_resid = len;
177 #if defined(AFS_XBSD_ENV)
178         tiovec[0].iov_base = abp->b_saveaddr;
179 #else
180         tiovec[0].iov_base = abp->b_un.b_addr;
181 #endif /* AFS_XBSD_ENV */
182         tiovec[0].iov_len = len;
183         /* are user's credentials valid here?  probably, but this
184          * sure seems like the wrong things to do. */
185 #if     defined(AFS_SUN5_ENV)
186         code = afs_nlrdwr(VTOAFS(abp->b_vp), &tuio, UIO_WRITE, 0, credp);
187 #else
188         code = afs_rdwr(VTOAFS(abp->b_vp), &tuio, UIO_WRITE, 0, credp);
189 #endif
190     }
191
192 #if defined(AFS_DUX40_ENV) || defined (AFS_XBSD_ENV)
193     if (code) {
194         abp->b_error = code;
195 #if !defined(AFS_FBSD50_ENV)
196         abp->b_flags |= B_ERROR;
197 #endif
198     }
199 #endif
200
201 #if defined(AFS_AIX32_ENV)
202     crfree(credp);
203 #elif defined(AFS_DUX40_ENV)
204     biodone(abp);
205     if (code && !(abp->b_flags & B_READ)) {
206         /* prevent ubc from retrying writes */
207         AFS_GUNLOCK();
208         ubc_invalidate(AFSTOV(tvc)->v_object,
209                        (vm_offset_t) dbtob(abp->b_blkno), PAGE_SIZE, B_INVAL);
210         AFS_GLOCK();
211     }
212 #elif defined(AFS_FBSD60_ENV)
213     (*abp->b_iodone)(abp);
214 #elif defined(AFS_FBSD50_ENV)
215     biodone(&abp->b_io);
216 #elif defined(AFS_XBSD_ENV)
217     biodone(abp);
218 #elif !defined(AFS_SUN5_ENV)
219     iodone(abp);
220 #endif
221
222     afs_Trace3(afs_iclSetp, CM_TRACE_STRATEGYDONE, ICL_TYPE_POINTER, tvc,
223                ICL_TYPE_INT32, code, ICL_TYPE_LONG, tuio.afsio_resid);
224     return code;
225 }
226
227 #endif /* !AFS_HPUX_ENV  && !AFS_SGI_ENV && !AFS_LINUX20_ENV */