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
10 #include <afsconfig.h>
11 #include "afs/param.h"
13 #include "afs/sysincludes.h" /* Standard vendor system headers */
14 #ifndef AFS_LINUX22_ENV
15 #include "rpc/types.h"
23 #endif /* AFS_ALPHA_ENV */
24 #include "afsincludes.h" /* Afs-based standard headers */
25 #include "afs/afs_stats.h" /* statistics */
26 #include "afs_prototypes.h"
29 * afs_UFSCacheStoreProc
35 * acall : Ptr to the Rx call structure involved.
36 * afile : Ptr to the related file descriptor.
37 * alen : Size of the file in bytes.
38 * avc : Ptr to the vcache entry.
39 * shouldWake : is it "safe" to return early from close() ?
40 * abytesToXferP : Set to the number of bytes to xfer.
41 * NOTE: This parameter is only used if AFS_NOSTATS
43 * abytesXferredP : Set to the number of bytes actually xferred.
44 * NOTE: This parameter is only used if AFS_NOSTATS
48 * Nothing interesting.
51 afs_UFSCacheStoreProc(register struct rx_call *acall, struct osi_file *afile,
52 register afs_int32 alen, struct vcache *avc,
53 int *shouldWake, afs_size_t * abytesToXferP,
54 afs_size_t * abytesXferredP)
57 register char *tbuffer;
60 AFS_STATCNT(UFS_CacheStoreProc);
64 * In this case, alen is *always* the amount of data we'll be trying
67 (*abytesToXferP) = alen;
68 (*abytesXferredP) = 0;
69 #endif /* AFS_NOSTATS */
71 afs_Trace4(afs_iclSetp, CM_TRACE_STOREPROC, ICL_TYPE_POINTER, avc,
72 ICL_TYPE_FID, &(avc->f.fid), ICL_TYPE_OFFSET,
73 ICL_HANDLE_OFFSET(avc->f.m.Length), ICL_TYPE_INT32, alen);
74 tbuffer = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
76 tlen = (alen > AFS_LRALLOCSIZ ? AFS_LRALLOCSIZ : alen);
77 got = afs_osi_Read(afile, -1, tbuffer, tlen);
79 #if defined(KERNEL_HAVE_UERROR)
80 || (got != tlen && getuerror())
83 osi_FreeLargeSpace(tbuffer);
86 afs_Trace2(afs_iclSetp, CM_TRACE_STOREPROC2, ICL_TYPE_OFFSET,
87 ICL_HANDLE_OFFSET(*tbuffer), ICL_TYPE_INT32, got);
89 code = rx_Write(acall, tbuffer, got); /* writing 0 bytes will
90 * push a short packet. Is that really what we want, just because the
91 * data didn't come back from the disk yet? Let's try it and see. */
94 (*abytesXferredP) += code;
95 #endif /* AFS_NOSTATS */
97 code = rx_Error(acall);
98 osi_FreeLargeSpace(tbuffer);
99 return code ? code : -33;
103 * If file has been locked on server, we can allow the store
106 if (shouldWake && *shouldWake && (rx_GetRemoteStatus(acall) & 1)) {
107 *shouldWake = 0; /* only do this once */
111 afs_Trace4(afs_iclSetp, CM_TRACE_STOREPROC, ICL_TYPE_POINTER, avc,
112 ICL_TYPE_FID, &(avc->f.fid), ICL_TYPE_OFFSET,
113 ICL_HANDLE_OFFSET(avc->f.m.Length), ICL_TYPE_INT32, alen);
114 osi_FreeLargeSpace(tbuffer);
117 } /* afs_UFSCacheStoreProc */
121 * afs_UFSCacheFetchProc
124 * Routine called on fetch; also tells people waiting for data
125 * that more has arrived.
128 * acall : Ptr to the Rx call structure.
129 * afile : File descriptor for the cache file.
130 * abase : Base offset to fetch.
131 * adc : Ptr to the dcache entry for the file, write-locked.
132 * avc : Ptr to the vcache entry for the file.
133 * abytesToXferP : Set to the number of bytes to xfer.
134 * NOTE: This parameter is only used if AFS_NOSTATS
136 * abytesXferredP : Set to the number of bytes actually xferred.
137 * NOTE: This parameter is only used if AFS_NOSTATS
141 * Nothing interesting.
145 afs_UFSCacheFetchProc(register struct rx_call *acall, struct osi_file *afile,
146 afs_size_t abase, struct dcache *adc,
147 struct vcache *avc, afs_size_t * abytesToXferP,
148 afs_size_t * abytesXferredP, afs_int32 lengthFound)
151 register afs_int32 code;
152 register char *tbuffer;
156 AFS_STATCNT(UFS_CacheFetchProc);
157 osi_Assert(WriteLocked(&adc->lock));
158 afile->offset = 0; /* Each time start from the beginning */
159 length = lengthFound;
161 (*abytesToXferP) = 0;
162 (*abytesXferredP) = 0;
163 #endif /* AFS_NOSTATS */
164 tbuffer = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
165 adc->validPos = abase;
169 code = rx_Read(acall, (char *)&length, sizeof(afs_int32));
171 length = ntohl(length);
172 if (code != sizeof(afs_int32)) {
173 osi_FreeLargeSpace(tbuffer);
174 code = rx_Error(acall);
175 return (code ? code : -1); /* try to return code, not -1 */
179 * The fetch protocol is extended for the AFS/DFS translator
180 * to allow multiple blocks of data, each with its own length,
181 * to be returned. As long as the top bit is set, there are more
184 * We do not do this for AFS file servers because they sometimes
185 * return large negative numbers as the transfer size.
187 if (avc->f.states & CForeign) {
188 moredata = length & 0x80000000;
189 length &= ~0x80000000;
194 (*abytesToXferP) += length;
195 #endif /* AFS_NOSTATS */
197 tlen = (length > AFS_LRALLOCSIZ ? AFS_LRALLOCSIZ : length);
198 #ifdef RX_KERNEL_TRACE
199 afs_Trace1(afs_iclSetp, CM_TRACE_TIMESTAMP, ICL_TYPE_STRING,
203 code = rx_Read(acall, tbuffer, tlen);
205 #ifdef RX_KERNEL_TRACE
206 afs_Trace1(afs_iclSetp, CM_TRACE_TIMESTAMP, ICL_TYPE_STRING,
210 (*abytesXferredP) += code;
211 #endif /* AFS_NOSTATS */
213 osi_FreeLargeSpace(tbuffer);
214 afs_Trace3(afs_iclSetp, CM_TRACE_FETCH64READ,
215 ICL_TYPE_POINTER, avc, ICL_TYPE_INT32, code,
216 ICL_TYPE_INT32, length);
219 code = afs_osi_Write(afile, -1, tbuffer, tlen);
221 osi_FreeLargeSpace(tbuffer);
226 adc->validPos = abase;
227 if (afs_osi_Wakeup(&adc->validPos) == 0)
228 afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAKE, ICL_TYPE_STRING,
229 __FILE__, ICL_TYPE_INT32, __LINE__,
230 ICL_TYPE_POINTER, adc, ICL_TYPE_INT32,
234 osi_FreeLargeSpace(tbuffer);
237 } /* afs_UFSCacheFetchProc */
240 afs_MemCacheStoreProc(register struct rx_call *acall,
241 register struct osi_file *fP,
242 register afs_int32 alen, struct vcache *avc,
243 int *shouldWake, afs_size_t * abytesToXferP,
244 afs_size_t * abytesXferredP)
246 register struct memCacheEntry *mceP = (struct memCacheEntry *)fP;
248 register afs_int32 code;
251 struct iovec *tiov; /* no data copying with iovec */
252 int tnio; /* temp for iovec size */
254 AFS_STATCNT(afs_MemCacheStoreProc);
257 * In this case, alen is *always* the amount of data we'll be trying
260 *(abytesToXferP) = alen;
261 *(abytesXferredP) = 0;
262 #endif /* AFS_NOSTATS */
265 * We need to alloc the iovecs on the heap so that they are "pinned" rather than
266 * declare them on the stack - defect 11272
269 (struct iovec *)osi_AllocSmallSpace(sizeof(struct iovec) *
273 ("afs_MemCacheStoreProc: osi_AllocSmallSpace for iovecs returned NULL\n");
276 /* do this at a higher level now -- it's a parameter */
277 /* for now, only do 'continue from close' code if file fits in one
278 * chunk. Could clearly do better: if only one modified chunk
279 * then can still do this. can do this on *last* modified chunk */
280 tlen = avc->f.m.Length - 1; /* byte position of last byte we'll store */
282 if (AFS_CHUNK(tlen) != 0)
290 tlen = (alen > AFS_LRALLOCSIZ ? AFS_LRALLOCSIZ : alen);
292 code = rx_WritevAlloc(acall, tiov, &tnio, RX_MAXIOVECS, tlen);
295 code = rx_Error(acall);
296 osi_FreeSmallSpace(tiov);
297 return code ? code : -33;
300 code = afs_MemReadvBlk(mceP, offset, tiov, tnio, tlen);
302 osi_FreeSmallSpace(tiov);
306 code = rx_Writev(acall, tiov, tnio, tlen);
309 (*abytesXferredP) += code;
310 #endif /* AFS_NOSTATS */
312 code = rx_Error(acall);
313 osi_FreeSmallSpace(tiov);
314 return code ? code : -33;
318 /* if file has been locked on server, can allow store to continue */
319 if (shouldWake && *shouldWake && (rx_GetRemoteStatus(acall) & 1)) {
320 *shouldWake = 0; /* only do this once */
324 osi_FreeSmallSpace(tiov);
329 afs_MemCacheFetchProc(register struct rx_call *acall,
330 register struct osi_file *fP, afs_size_t abase,
331 struct dcache *adc, struct vcache *avc,
332 afs_size_t * abytesToXferP, afs_size_t * abytesXferredP,
333 afs_int32 lengthFound)
335 register struct memCacheEntry *mceP = (struct memCacheEntry *)fP;
336 register afs_int32 code;
339 struct iovec *tiov; /* no data copying with iovec */
340 register int tlen, offset = 0;
341 int tnio; /* temp for iovec size */
343 AFS_STATCNT(afs_MemCacheFetchProc);
344 length = lengthFound;
345 afs_Trace4(afs_iclSetp, CM_TRACE_MEMFETCH, ICL_TYPE_POINTER, avc,
346 ICL_TYPE_POINTER, mceP, ICL_TYPE_OFFSET,
347 ICL_HANDLE_OFFSET(abase), ICL_TYPE_INT32, length);
349 (*abytesToXferP) = 0;
350 (*abytesXferredP) = 0;
351 #endif /* AFS_NOSTATS */
353 * We need to alloc the iovecs on the heap so that they are "pinned" rather than
354 * declare them on the stack - defect 11272
357 (struct iovec *)osi_AllocSmallSpace(sizeof(struct iovec) *
361 ("afs_MemCacheFetchProc: osi_AllocSmallSpace for iovecs returned NULL\n");
363 adc->validPos = abase;
367 code = rx_Read(acall, (char *)&length, sizeof(afs_int32));
368 length = ntohl(length);
370 if (code != sizeof(afs_int32)) {
371 code = rx_Error(acall);
372 osi_FreeSmallSpace(tiov);
373 return (code ? code : -1); /* try to return code, not -1 */
377 * The fetch protocol is extended for the AFS/DFS translator
378 * to allow multiple blocks of data, each with its own length,
379 * to be returned. As long as the top bit is set, there are more
382 * We do not do this for AFS file servers because they sometimes
383 * return large negative numbers as the transfer size.
385 if (avc->f.states & CForeign) {
386 moredata = length & 0x80000000;
387 length &= ~0x80000000;
392 (*abytesToXferP) += length;
393 #endif /* AFS_NOSTATS */
395 tlen = (length > AFS_LRALLOCSIZ ? AFS_LRALLOCSIZ : length);
397 code = rx_Readv(acall, tiov, &tnio, RX_MAXIOVECS, tlen);
400 (*abytesXferredP) += code;
401 #endif /* AFS_NOSTATS */
403 afs_Trace3(afs_iclSetp, CM_TRACE_FETCH64READ,
404 ICL_TYPE_POINTER, avc, ICL_TYPE_INT32, code,
405 ICL_TYPE_INT32, length);
406 osi_FreeSmallSpace(tiov);
410 afs_MemWritevBlk(mceP, offset, tiov, tnio, tlen);
414 adc->validPos = abase;
415 if (afs_osi_Wakeup(&adc->validPos) == 0)
416 afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAKE, ICL_TYPE_STRING,
417 __FILE__, ICL_TYPE_INT32, __LINE__,
418 ICL_TYPE_POINTER, adc, ICL_TYPE_INT32,
422 /* max of two sizes */
423 osi_FreeSmallSpace(tiov);