Initial IBM OpenAFS 1.0 tree
[openafs.git] / src / afs / VNOPS / afs_vnop_strategy.c
1 /* Copyright (C) 1995, 1989, 1998 Transarc Corporation - All rights reserved */
2 /*
3  * (C) COPYRIGHT IBM CORPORATION 1987, 1988
4  * LICENSED MATERIALS - PROPERTY OF IBM
5  */
6 /*
7  * afs_vnop_strategy.c
8  *
9  * Implements:
10  * afs_ustrategy
11  */
12
13 #include "../afs/param.h"       /* Should be always first */
14 #if !defined(AFS_HPUX_ENV) && !defined(AFS_SGI_ENV) && !defined(AFS_LINUX20_ENV)
15
16 #include "../afs/sysincludes.h" /* Standard vendor system headers */
17 #include "../afs/afsincludes.h" /* Afs-based standard headers */
18 #include "../afs/afs_stats.h" /* statistics */
19 #include "../afs/afs_cbqueue.h"
20 #include "../afs/nfsclient.h"
21 #include "../afs/afs_osidnlc.h"
22
23
24
25
26 #if     defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV)
27 afs_ustrategy(abp, credp)
28     struct AFS_UCRED *credp;
29 #else
30 afs_ustrategy(abp)
31 #endif
32     register struct buf *abp; {
33     register afs_int32 code;
34     struct uio tuio;
35     register struct vcache *tvc = (struct vcache *) abp->b_vp;
36     register afs_int32 len = abp->b_bcount;
37 #if     !defined(AFS_SUN5_ENV) && !defined(AFS_OSF_ENV)
38 #ifdef  AFS_AIX41_ENV
39     struct ucred *credp;
40 #else
41     struct AFS_UCRED *credp = u.u_cred;
42 #endif
43 #endif
44 #if     defined(AFS_SUN_ENV) || defined(AFS_SUN5_ENV)
45     int async = abp->b_flags & B_ASYNC;
46 #endif
47     struct iovec tiovec[1];
48
49     AFS_STATCNT(afs_ustrategy);
50 #ifdef  AFS_AIX41_ENV
51     /*
52      * So that it won't change while reading it
53      */
54     ObtainReadLock(&tvc->lock);
55     if (tvc->credp) {   
56         credp = tvc->credp;
57         crhold(credp);
58     } else {
59         credp = crref();
60     }
61     ReleaseReadLock(&tvc->lock);
62     osi_Assert(credp);
63 #endif
64     if ((abp->b_flags & B_READ) == B_READ) {
65         /* read b_bcount bytes into kernel address b_un.b_addr starting
66             at byte DEV_BSIZE * b_blkno.  Bzero anything we can't read,
67             and finally call iodone(abp).  File is in abp->b_vp.  Credentials
68             are from u area??
69         */
70         tuio.afsio_iov = tiovec;
71         tuio.afsio_iovcnt = 1;
72 #if     defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
73         tuio.afsio_offset = (u_int) dbtob(abp->b_blkno);
74 #if     defined(AFS_SUN5_ENV)
75         tuio._uio_offset._p._u = 0;
76 #endif
77 #else
78         tuio.afsio_offset = DEV_BSIZE * abp->b_blkno;
79 #endif
80         tuio.afsio_seg = AFS_UIOSYS;
81 #ifdef AFS_UIOFMODE
82         tuio.afsio_fmode = 0;
83 #endif
84         tuio.afsio_resid = abp->b_bcount;
85         tiovec[0].iov_base = abp->b_un.b_addr;
86         tiovec[0].iov_len = abp->b_bcount;
87         /* are user's credentials valid here?  probably, but this
88              sure seems like the wrong things to do. */
89 #if     defined(AFS_SUN5_ENV)
90         code = afs_nlrdwr((struct vcache *) abp->b_vp, &tuio, UIO_READ, 0, credp);
91 #else
92         code = afs_rdwr((struct vcache *) abp->b_vp, &tuio, UIO_READ, 0, credp);
93 #endif
94         if (code == 0) {
95             if (tuio.afsio_resid > 0)
96                 bzero(abp->b_un.b_addr + abp->b_bcount - tuio.afsio_resid, tuio.afsio_resid);
97 #ifdef  AFS_AIX32_ENV
98             /*
99              * If we read a block that is past EOF and the user was not storing
100              * to it, go ahead and write protect the page. This way we will detect
101              * storing beyond EOF in the future
102              */
103             if (dbtob(abp->b_blkno) + abp->b_bcount > tvc->m.Length) {
104                 if ((abp->b_flags & B_PFSTORE) == 0) {
105                     AFS_GUNLOCK();
106                     vm_protectp(tvc->vmh, dbtob(abp->b_blkno)/PAGESIZE,
107                                 abp->b_bcount/PAGESIZE, RDONLY);
108                     AFS_GLOCK();
109                 }
110             }
111 #endif
112         }
113     }
114     else {
115         tuio.afsio_iov = tiovec;
116         tuio.afsio_iovcnt = 1;
117 #if     defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
118         tuio.afsio_offset = (u_int) dbtob(abp->b_blkno);
119 #ifdef  AFS_SUN5_ENV
120         tuio._uio_offset._p._u = 0;
121         tuio.uio_limit = u.u_rlimit[RLIMIT_FSIZE].rlim_cur;
122 #endif
123 #else
124         tuio.afsio_offset = DEV_BSIZE * abp->b_blkno;
125 #endif
126         tuio.afsio_seg = AFS_UIOSYS;
127 #ifdef AFS_UIOFMODE
128         tuio.afsio_fmode = 0;
129 #endif
130 #ifdef  AFS_AIX32_ENV   
131         /*
132          * XXX It this really right? Ideally we should always write block size multiple
133          * and not any arbitrary size, right? XXX
134          */
135         len = MIN(len, tvc->m.Length - dbtob(abp->b_blkno));
136 #endif
137 #ifdef  AFS_ALPHA_ENV
138         len = MIN(abp->b_bcount, ((struct vcache *)abp->b_vp)->m.Length - dbtob(abp->b_blkno));
139 #endif  /* AFS_ALPHA_ENV */
140         tuio.afsio_resid = len;
141         tiovec[0].iov_base = abp->b_un.b_addr;
142         tiovec[0].iov_len = len;
143         /* are user's credentials valid here?  probably, but this
144              sure seems like the wrong things to do. */
145 #if     defined(AFS_SUN5_ENV)
146         code = afs_nlrdwr((struct vcache *) abp->b_vp, &tuio, UIO_WRITE, 0, credp);
147 #else
148         code = afs_rdwr((struct vcache *) abp->b_vp, &tuio, UIO_WRITE, 0, credp);
149 #endif
150     }
151 #if     !defined(AFS_AIX32_ENV) && !defined(AFS_SUN5_ENV)
152 #ifdef AFS_DUX40_ENV
153     if (code) {
154         abp->b_error = code;
155         abp->b_flags |= B_ERROR;
156     }
157     biodone(abp);
158     if (code && !(abp->b_flags & B_READ)) {
159         /* prevent ubc from retrying writes */
160         AFS_GUNLOCK();
161         ubc_invalidate(((struct vnode *)tvc)->v_object,
162                        (vm_offset_t)dbtob(abp->b_blkno),
163                        PAGE_SIZE, B_INVAL);
164         AFS_GLOCK();
165     }
166 #else  /* AFS_DUX40_ENV */
167     iodone(abp);
168 #endif /* AFS_DUX40_ENV */
169 #endif
170 #ifdef  AFS_AIX32_ENV
171     crfree(credp);
172 #endif
173     afs_Trace3(afs_iclSetp, CM_TRACE_STRATEGYDONE, ICL_TYPE_POINTER, tvc,
174                ICL_TYPE_INT32, code,
175                ICL_TYPE_LONG, tuio.afsio_resid);
176     return code;
177 }
178
179 #endif /* !AFS_HPUX_ENV  && !AFS_SGI_ENV && !AFS_LINUX20_ENV */