afsconfig-and-rcsid-all-around-20010705
[openafs.git] / src / afs / FBSD / osi_vnodeops.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  * vnodeops structure and Digital Unix specific ops and support routines.
12  */
13
14 #include "../afs/param.h"       /* Should be always first */
15 #include <afsconfig.h>
16
17 RCSID("$Header$");
18
19
20 #include "../afs/sysincludes.h" /* Standard vendor system headers */
21 #include "../afs/afsincludes.h" /* Afs-based standard headers */
22 #include "../afs/afs_stats.h" /* statistics */
23 #include <vm/vm.h>
24 #include <vm/vnode_pager.h>
25 #include <vm/vm_map.h>
26 /* #include <vm/vm_ubc.h> */
27 #include "../afs/afs_cbqueue.h"
28 #include "../afs/nfsclient.h"
29 #include "../afs/afs_osidnlc.h"
30
31
32 extern int afs_lookup(), afs_create(), afs_noop(), afs_open(), afs_close();
33 extern int afs_access(), afs_getattr(), afs_setattr(), afs_badop();
34 extern int afs_fsync(), afs_seek(), afs_remove(), afs_link(), afs_rename();
35 extern int afs_mkdir(), afs_rmdir(), afs_symlink(), afs_readdir();
36 extern int afs_readlink(), afs_lockctl();
37 extern int vn_pathconf_default(), seltrue();
38
39 int mp_afs_lookup(), mp_afs_create(), mp_afs_open();
40 int mp_afs_access(), mp_afs_getattr(), mp_afs_setattr(), mp_afs_ubcrdwr();
41 int mp_afs_ubcrdwr(), mp_afs_mmap();
42 int mp_afs_fsync(), mp_afs_seek(), mp_afs_remove(), mp_afs_link();
43 int mp_afs_rename(), mp_afs_mkdir(), mp_afs_rmdir(), mp_afs_symlink();
44 int mp_afs_readdir(), mp_afs_readlink(), mp_afs_abortop(), mp_afs_inactive();
45 int mp_afs_reclaim(), mp_afs_bmap(), mp_afs_strategy(), mp_afs_print();
46 int mp_afs_page_read(), mp_afs_page_write(), mp_afs_swap(), mp_afs_bread();
47 int mp_afs_brelse(), mp_afs_lockctl(), mp_afs_syncdata(), mp_afs_close();
48 int mp_afs_closex();
49
50 #if 0
51 /* AFS vnodeops */
52 struct vnodeops Afs_vnodeops = {
53         mp_afs_lookup,
54         mp_afs_create,
55         afs_noop,       /* vn_mknod */
56         mp_afs_open,
57         mp_afs_close,
58         mp_afs_access,
59         mp_afs_getattr,
60         mp_afs_setattr,
61         mp_afs_ubcrdwr,
62         mp_afs_ubcrdwr,
63         afs_badop,      /* vn_ioctl */
64         seltrue,        /* vn_select */
65         mp_afs_mmap,
66         mp_afs_fsync,
67         mp_afs_seek,
68         mp_afs_remove,
69         mp_afs_link,
70         mp_afs_rename,
71         mp_afs_mkdir,
72         mp_afs_rmdir,
73         mp_afs_symlink,
74         mp_afs_readdir,
75         mp_afs_readlink,
76         mp_afs_abortop,
77         mp_afs_inactive,
78         mp_afs_reclaim,
79         mp_afs_bmap,
80         mp_afs_strategy,
81         mp_afs_print,
82         mp_afs_page_read,
83         mp_afs_page_write,
84         mp_afs_swap,
85         mp_afs_bread,
86         mp_afs_brelse,
87         mp_afs_lockctl,
88         mp_afs_syncdata,
89         afs_noop,       /* Lock */
90         afs_noop,       /* unLock */
91         afs_noop,       /* get ext attrs */
92         afs_noop,       /* set ext attrs */
93         afs_noop,       /* del ext attrs */
94         vn_pathconf_default,
95 };
96 struct vnodeops *afs_ops = &Afs_vnodeops;
97 #endif /* 0 */
98
99 /* vnode file operations, and our own */
100 extern int vn_read();
101 extern int vn_write();
102 extern int vn_ioctl();
103 extern int vn_select();
104 extern int afs_closex();
105
106 struct fileops afs_fileops = {
107     vn_read,
108     vn_write,
109     vn_ioctl,
110     vn_select,
111     mp_afs_closex,
112 };
113
114 #if 0
115 mp_afs_lookup(adp, ndp)
116     struct vcache *adp;
117     struct nameidata *ndp;
118 {
119     int code;
120     AFS_GLOCK();
121     code = afs_lookup(adp, ndp);
122     AFS_GUNLOCK();
123     return code;
124 }
125
126 mp_afs_create(ndp, attrs)
127     struct nameidata *ndp;
128     struct vattr *attrs;
129 {
130     int code;
131     AFS_GLOCK();
132     code = afs_create(ndp, attrs);
133     AFS_GUNLOCK();
134     return code;
135 }
136
137 mp_afs_open(avcp, aflags, acred)
138     struct vcache **avcp;
139     afs_int32 aflags;
140     struct AFS_UCRED *acred;
141 {
142     int code;
143     AFS_GLOCK();
144     code = afs_open(avcp, aflags, acred);
145     AFS_GUNLOCK();
146     return code;
147 }
148
149 mp_afs_access(avc, amode, acred)
150     struct vcache *avc;
151     afs_int32 amode;
152     struct AFS_UCRED *acred;
153 {
154     int code;
155     AFS_GLOCK();
156     code = afs_access(avc, amode, acred);
157     AFS_GUNLOCK();
158     return code;
159 }
160
161 mp_afs_close(avc, flags, cred)
162     struct vnode *avc;
163     int flags;
164     struct ucred *cred;
165 {
166     int code;
167     AFS_GLOCK();
168     code = afs_close(avc, flags, cred);
169     AFS_GUNLOCK();
170     return code;
171 }
172
173 mp_afs_getattr(avc, attrs, acred)
174     struct vcache *avc;
175     struct vattr *attrs;
176     struct AFS_UCRED *acred;
177 {
178     int code;
179     AFS_GLOCK();
180     code = afs_getattr(avc, attrs, acred);
181     AFS_GUNLOCK();
182     return code;
183 }
184
185 mp_afs_setattr(avc, attrs, acred)
186     struct vcache *avc;
187     struct vattr *attrs;
188     struct AFS_UCRED *acred;
189 {
190     int code;
191     AFS_GLOCK();
192     code = afs_setattr(avc, attrs, acred);
193     AFS_GUNLOCK();
194     return code;
195 }
196
197 mp_afs_fsync(avc, fflags, acred, waitfor)
198     struct vcache *avc;
199     int fflags;
200     struct AFS_UCRED *acred;
201     int waitfor;
202 {
203     int code;
204     AFS_GLOCK();
205     code = afs_fsync(avc, fflags, acred, waitfor);
206     AFS_GUNLOCK();
207     return code;
208 }
209
210 mp_afs_remove(ndp)
211     struct nameidata *ndp;
212 {
213     int code;
214     AFS_GLOCK();
215     code = afs_remove(ndp);
216     AFS_GUNLOCK();
217     return code;
218 }
219
220 mp_afs_link(avc, ndp)
221     struct vcache *avc;
222     struct nameidata *ndp;
223 {
224     int code;
225     AFS_GLOCK();
226     code = afs_link(avc, ndp);
227     AFS_GUNLOCK();
228     return code;
229 }
230
231 mp_afs_rename(fndp, tndp)
232     struct nameidata *fndp, *tndp;
233 {
234     int code;
235     AFS_GLOCK();
236     code = afs_rename(fndp, tndp);
237     AFS_GUNLOCK();
238     return code;
239 }
240
241 mp_afs_mkdir(ndp, attrs)
242     struct nameidata *ndp;
243     struct vattr *attrs;
244 {
245     int code;
246     AFS_GLOCK();
247     code = afs_mkdir(ndp, attrs);
248     AFS_GUNLOCK();
249     return code;
250 }
251
252 mp_afs_rmdir(ndp)
253     struct nameidata *ndp;
254 {
255     int code;
256     AFS_GLOCK();
257     code = afs_rmdir(ndp);
258     AFS_GUNLOCK();
259     return code;
260 }
261
262 mp_afs_symlink(ndp, attrs, atargetName)
263     struct nameidata *ndp;
264     struct vattr *attrs;
265     register char *atargetName;
266 {
267     int code;
268     AFS_GLOCK();
269     code = afs_symlink(ndp, attrs, atargetName);
270     AFS_GUNLOCK();
271     return code;
272 }
273
274 mp_afs_readdir(avc, auio, acred, eofp)
275     struct vcache *avc;
276     struct uio *auio;
277     struct AFS_UCRED *acred;
278     int *eofp;
279 {
280     int code;
281     AFS_GLOCK();
282     code = afs_readdir(avc, auio, acred, eofp);
283     AFS_GUNLOCK();
284     return code;
285 }
286
287 mp_afs_readlink(avc, auio, acred)
288     struct vcache *avc;
289     struct uio *auio;
290     struct AFS_UCRED *acred;
291 {
292     int code;
293     AFS_GLOCK();
294     code = afs_readlink(avc, auio, acred);
295     AFS_GUNLOCK();
296     return code;
297 }
298
299 mp_afs_lockctl(avc, af, flag, acred, clid, offset)
300     struct vcache *avc;
301     struct eflock *af;
302     struct AFS_UCRED *acred;
303     int flag;
304     pid_t clid;
305     off_t offset;
306 {
307     int code;
308     AFS_GLOCK();
309     code = afs_lockctl(avc, af, flag, acred, clid, offset);
310     AFS_GUNLOCK();
311     return code;
312 }
313
314 mp_afs_closex(afd)
315     struct file *afd;
316 {
317     int code;
318     AFS_GLOCK();
319     code = afs_closex(afd);
320     AFS_GUNLOCK();
321     return code;
322 }
323
324 mp_afs_seek(avc, oldoff, newoff, cred)
325     struct vcache *avc;
326     off_t oldoff, newoff;
327     struct ucred *cred;
328 {
329     if ((int) newoff < 0)
330         return(EINVAL);
331     else
332         return(0);
333 }
334
335 mp_afs_abortop(ndp)
336     struct nameidata *ndp;
337 {
338     return(0);
339 }
340
341 mp_afs_inactive(avc, acred)
342     register struct vcache *avc;
343     struct AFS_UCRED *acred;
344 {
345     AFS_GLOCK();
346     afs_InactiveVCache(avc, acred);
347     AFS_GUNLOCK();
348 }
349
350
351 mp_afs_reclaim(avc)
352     struct vcache *avc;
353 {
354     return(0);
355 }
356
357 mp_afs_print(avc)
358     struct vcache *avc;
359 {
360     return(0);
361 }
362
363 mp_afs_page_read(avc, uio, acred)
364     struct vcache *avc;
365     struct uio *uio;
366     struct ucred *acred;
367 {
368     int error;
369     struct vrequest treq;
370
371     AFS_GLOCK();
372     error = afs_rdwr(avc, uio, UIO_READ, 0, acred);
373     afs_Trace3(afs_iclSetp, CM_TRACE_PAGE_READ, ICL_TYPE_POINTER, avc,
374                ICL_TYPE_INT32, error,  ICL_TYPE_INT32, avc->states);
375     if (error) {
376         error = EIO;
377     } else if ((avc->states) == 0) {
378         afs_InitReq(&treq, acred);
379         ObtainWriteLock(&avc->lock,161);
380         afs_Wire(avc, &treq);
381         ReleaseWriteLock(&avc->lock);
382     }
383     AFS_GUNLOCK();
384     return(error);
385 }
386
387
388 mp_afs_page_write(avc, uio, acred, pager, offset)
389     struct vcache *avc;
390     struct uio *uio;
391     struct ucred *acred;
392     memory_object_t pager;
393     vm_offset_t     offset;
394 {
395     int error;
396
397     AFS_GLOCK();
398     error = afs_rdwr(avc, uio, UIO_WRITE, 0, acred);
399     afs_Trace3(afs_iclSetp, CM_TRACE_PAGE_WRITE, ICL_TYPE_POINTER, avc,
400                ICL_TYPE_INT32, error, ICL_TYPE_INT32, avc->states);
401     if (error) {
402         error = EIO;
403     }
404     AFS_GUNLOCK();
405     return(error);
406 }
407
408
409 int DO_FLUSH=1;
410 mp_afs_ubcrdwr(avc, uio, ioflag, cred)
411     struct vcache *avc;
412     struct uio *uio;
413     int ioflag;
414     struct ucred *cred;
415 {
416     register afs_int32 code;
417     register char *data;
418     afs_int32 fileBase, size, cnt=0;
419     afs_int32 pageBase;
420     register afs_int32 tsize;
421     register afs_int32 pageOffset;
422     int eof;
423     struct vrequest treq;
424     int rw = uio->uio_rw;
425     int rv, flags;
426     int newpage=0;
427     vm_page_t page;
428     afs_int32 save_resid;
429     struct dcache *tdc;
430     int didFakeOpen=0;
431     int counter=0;
432
433     AFS_GLOCK();
434     afs_InitReq(&treq, cred);
435     if (AFS_NFSXLATORREQ(cred) && rw == UIO_READ) {
436         if (!afs_AccessOK(avc, PRSFS_READ, &treq,
437                           CHECK_MODE_BITS|CMB_ALLOW_EXEC_AS_READ))  {
438             AFS_GUNLOCK();
439             return EACCES;
440         }
441     }
442     afs_Trace4(afs_iclSetp, CM_TRACE_VMRW, ICL_TYPE_POINTER, avc,
443                ICL_TYPE_INT32, (rw==UIO_WRITE? 1 : 0),
444                ICL_TYPE_LONG, uio->uio_offset,
445                ICL_TYPE_LONG, uio->uio_resid);
446     code = afs_VerifyVCache(avc, &treq);
447     if (code) {
448         code = afs_CheckCode(code, &treq, 35);
449         AFS_GUNLOCK();
450         return code;
451     }
452     if (vType(avc) != VREG) {
453         AFS_GUNLOCK();
454         return EISDIR;  /* can't read or write other things */
455     }
456     afs_BozonLock(&avc->pvnLock, avc);
457     osi_FlushPages(avc);        /* hold bozon lock, but not basic vnode lock */
458     ObtainWriteLock(&avc->lock,162);
459     /* adjust parameters when appending files */
460     if ((ioflag & IO_APPEND) && uio->uio_rw == UIO_WRITE)
461         uio->uio_offset = avc->m.Length;        /* write at EOF position */
462     if (uio->uio_rw == UIO_WRITE) {
463         avc->states |= CDirty;
464         afs_FakeOpen(avc);
465         didFakeOpen=1;
466         /*
467          * before starting any I/O, we must ensure that the file is big enough
468          * to hold the results (since afs_putpage will be called to force
469          * the I/O.
470          */
471         size = uio->afsio_resid + uio->afsio_offset;    /* new file size */
472         if (size > avc->m.Length) avc->m.Length = size; /* file grew */
473         avc->m.Date = osi_Time();       /* Set file date (for ranlib) */
474         if (uio->afsio_resid > PAGE_SIZE)
475             cnt = uio->afsio_resid / PAGE_SIZE;
476         save_resid = uio->afsio_resid;
477     }
478
479     while (1) {
480         /*
481          * compute the amount of data to move into this block,
482          * based on uio->afsio_resid.
483          */
484         size = uio->afsio_resid;                /* transfer size */
485         fileBase = uio->afsio_offset;           /* start file position */
486         pageBase = fileBase & ~(PAGE_SIZE-1);   /* file position of the page */
487         pageOffset = fileBase & (PAGE_SIZE-1);  /* start offset within page */
488         tsize = PAGE_SIZE-pageOffset;           /* amount left in this page */
489         /*
490          * we'll read tsize bytes,
491          * but first must make sure tsize isn't too big
492          */
493         if (tsize > size) tsize = size; /* don't read past end of request */
494         eof = 0;        /* flag telling us if we hit the EOF on the read */
495         if (uio->uio_rw == UIO_READ) {  /* we're doing a read operation */
496             /* don't read past EOF */
497             if (tsize + fileBase > avc->m.Length) {
498                 tsize = avc->m.Length - fileBase;
499                 eof = 1;        /* we did hit the EOF */
500                 if (tsize < 0) tsize = 0;       /* better safe than sorry */
501             }
502         }
503         if (tsize <= 0) break;  /* nothing to transfer, we're done */
504
505         /* Purge dirty chunks of file if there are too many dirty chunks.
506          * Inside the write loop, we only do this at a chunk boundary.
507          * Clean up partial chunk if necessary at end of loop.
508          */
509         if (uio->uio_rw == UIO_WRITE && counter > 0
510             && AFS_CHUNKOFFSET(fileBase) == 0) {
511             code = afs_DoPartialWrite(avc, &treq);
512             avc->states |= CDirty;
513         }
514
515         if (code) {
516             break;
517         }
518
519         flags = 0;
520         ReleaseWriteLock(&avc->lock);
521         AFS_GUNLOCK();
522         code = ubc_lookup(((struct vnode *)avc)->v_object, pageBase,
523                           PAGE_SIZE, PAGE_SIZE, &page, &flags);
524         AFS_GLOCK();
525         ObtainWriteLock(&avc->lock,163);
526
527         if (code) {
528             break;
529         }
530         if (flags & B_NOCACHE) {
531             /*
532                No page found. We should not read the page in if
533                1. the write starts on a page edge (ie, pageoffset == 0)
534                and either
535                      1. we will fill the page  (ie, size == PAGESIZE), or
536                      2. we are writing past eof
537              */
538             if ((uio->uio_rw == UIO_WRITE) &&
539                 ((pageOffset == 0 && (size == PAGE_SIZE || fileBase >= avc->m.Length)))) {
540                 struct vnode *vp = (struct vnode *)avc;
541                 /* we're doing a write operation past eof; no need to read it */
542                 newpage = 1;
543                 AFS_GUNLOCK();
544                 ubc_page_zero(page, 0, PAGE_SIZE);
545                 ubc_page_release(page, B_DONE);
546                 AFS_GLOCK();
547             } else {
548                 /* page wasn't cached, read it in. */
549                 struct buf *bp;
550
551                 AFS_GUNLOCK();
552                 bp = ubc_bufalloc(page, 1, PAGE_SIZE, 1, B_READ);
553                 AFS_GLOCK();
554                 bp->b_dev = 0;
555                 bp->b_vp = (struct vnode *)avc;
556                 bp->b_blkno = btodb(pageBase);
557                 ReleaseWriteLock(&avc->lock);
558                 code = afs_ustrategy(bp, cred); /* do the I/O */
559                 ObtainWriteLock(&avc->lock,164);
560                 AFS_GUNLOCK();
561                 ubc_sync_iodone(bp);
562                 AFS_GLOCK();
563                 if (code) {
564                     AFS_GUNLOCK();
565                     ubc_page_release(page, 0);
566                     AFS_GLOCK();
567                     break;
568                 }
569             }
570         }
571         AFS_GUNLOCK();
572         ubc_page_wait(page);
573         data = (char *)page->pg_addr; /* DUX 4.0D */
574         if (data == 0)
575             data = (char *)PHYS_TO_KSEG(page->pg_phys_addr);  /* DUX 4.0E */
576         AFS_GLOCK();
577         ReleaseWriteLock(&avc->lock);   /* uiomove may page fault */
578         AFS_GUNLOCK();
579         code = uiomove(data+pageOffset, tsize, uio);
580         ubc_unload(page, pageOffset, page_size);
581         if (uio->uio_rw == UIO_WRITE) {
582                 vm_offset_t toffset;
583
584                 /* Mark the page dirty and release it to avoid a deadlock
585                  * in ubc_dirty_kluster when more than one process writes
586                  * this page at the same time. */
587                 toffset = page->pg_offset;
588                 flags |= B_DIRTY;
589                 ubc_page_release(page, flags);
590
591                 if (cnt > 10) {
592                     vm_page_t pl;
593                     int kpcnt;
594                     struct buf *bp;
595
596                     /* We released the page, so we can get a null page
597                      * list if another thread calls the strategy routine.
598                      */
599                     pl = ubc_dirty_kluster(((struct vnode *)avc)->v_object, 
600                            NULL, toffset, 0, B_WANTED, FALSE, &kpcnt);
601                     if (pl) {
602                         bp = ubc_bufalloc(pl, 1, PAGE_SIZE, 1, B_WRITE);
603                         bp->b_dev = 0;
604                         bp->b_vp = (struct vnode *)avc;
605                         bp->b_blkno = btodb(pageBase);
606                         AFS_GLOCK();
607                         code = afs_ustrategy(bp, cred); /* do the I/O */
608                         AFS_GUNLOCK();
609                         ubc_sync_iodone(bp);
610                         if (code) {
611                             AFS_GLOCK();
612                             ObtainWriteLock(&avc->lock,415);
613                             break;
614                         }
615                     }
616                 }
617         } else {
618             ubc_page_release(page, flags);
619         }
620         AFS_GLOCK();
621         ObtainWriteLock(&avc->lock,165);
622         /*
623          * If reading at a chunk boundary, start prefetch of next chunk.
624          */
625         if (uio->uio_rw == UIO_READ
626             && (counter == 0 || AFS_CHUNKOFFSET(fileBase) == 0)) {
627             tdc = afs_FindDCache(avc, fileBase);
628             if (tdc) {
629                 if (!(tdc->flags & DFNextStarted))
630                     afs_PrefetchChunk(avc, tdc, cred, &treq);
631                 afs_PutDCache(tdc);
632             }
633         }
634         counter++;
635         if (code) break;
636     }
637     if (didFakeOpen)
638         afs_FakeClose(avc, cred);
639     if (uio->uio_rw == UIO_WRITE && code == 0 && (avc->states & CDirty)) {
640         code = afs_DoPartialWrite(avc, &treq);
641     }
642     ReleaseWriteLock(&avc->lock);
643     afs_BozonUnlock(&avc->pvnLock, avc);
644     if (DO_FLUSH || (!newpage && (cnt < 10))) {
645         AFS_GUNLOCK();
646         ubc_flush_dirty(((struct vnode *)avc)->v_object, flags); 
647         AFS_GLOCK();
648     }
649
650     ObtainSharedLock(&avc->lock, 409);
651     if (!code) {
652         if (avc->vc_error) {
653             code = avc->vc_error;
654         }
655     }
656     /* This is required since we may still have dirty pages after the write.
657      * I could just let close do the right thing, but stat's before the close
658      * return the wrong length.
659      */
660     if (code == EDQUOT || code == ENOSPC) {
661         uio->uio_resid = save_resid;
662         UpgradeSToWLock(&avc->lock, 410);
663         osi_ReleaseVM(avc, cred);
664         ConvertWToSLock(&avc->lock);
665     }
666     ReleaseSharedLock(&avc->lock);
667
668     if (!code && (ioflag & IO_SYNC) && (uio->uio_rw == UIO_WRITE)
669         && !AFS_NFSXLATORREQ(cred)) {
670         code = afs_fsync(avc, 0, cred, 0);
671     }
672 out:
673     code = afs_CheckCode(code, &treq, 36);
674     AFS_GUNLOCK();
675     return code;
676 }
677
678
679 /*
680  * Now for some bad news.  Since we artificially hold on to vnodes by doing
681  * and extra VNHOLD in afs_NewVCache(), there is no way for us to know
682  * when we need to flush the pages when a program exits.  Particularly
683  * if it closes the file after mapping it R/W.
684  *
685  */
686
687 mp_afs_mmap(avc, offset, map, addrp, len, prot, maxprot, flags, cred)
688     register struct vcache *avc;
689     vm_offset_t offset;
690     vm_map_t map;
691     vm_offset_t *addrp;
692     vm_size_t len;
693     vm_prot_t prot;
694     vm_prot_t maxprot;
695     int flags;
696     struct ucred *cred;
697 {
698     struct vp_mmap_args args;
699     register struct vp_mmap_args *ap = &args;
700     struct vnode *vp = (struct vnode *)avc;
701     int code;
702     struct vrequest treq;
703 #if     !defined(DYNEL)
704     extern kern_return_t u_vp_create();
705 #endif
706
707     AFS_GLOCK();
708     afs_InitReq(&treq, cred);
709     code = afs_VerifyVCache(avc, &treq);
710     if (code) {
711       code = afs_CheckCode(code, &treq, 37);
712       AFS_GUNLOCK();
713       return code;
714     }
715     afs_BozonLock(&avc->pvnLock, avc);
716     osi_FlushPages(avc);        /* ensure old pages are gone */
717     afs_BozonUnlock(&avc->pvnLock, avc);
718     ObtainWriteLock(&avc->lock,166);
719     avc->states |= CMAPPED;
720     ReleaseWriteLock(&avc->lock);
721     ap->a_offset = offset;
722     ap->a_vaddr = addrp;
723     ap->a_size = len;
724     ap->a_prot = prot,
725     ap->a_maxprot = maxprot;
726     ap->a_flags = flags;
727     AFS_GUNLOCK();
728     code = u_vp_create(map, vp->v_object, (vm_offset_t) ap);
729     AFS_GLOCK();
730     code = afs_CheckCode(code, &treq, 38);
731     AFS_GUNLOCK();
732     return code;
733 }
734
735
736 int mp_afs_getpage(vop, offset, len, protp, pl, plsz, mape, addr, rw, cred)
737     vm_ubc_object_t vop;
738     vm_offset_t offset;
739     vm_size_t len;
740     vm_prot_t *protp;
741     vm_page_t *pl;
742     int plsz;
743     vm_map_entry_t mape;
744     vm_offset_t addr;
745     int rw;
746     struct ucred *cred;
747 {
748     register afs_int32 code;
749     struct vrequest treq;
750     int flags = 0;
751     int i, pages = (len + PAGE_SIZE - 1) >> page_shift;
752     vm_page_t *pagep;
753     vm_offset_t off;
754
755    struct vcache *avc =  (struct vcache *)vop->vu_vp;
756
757     /* first, obtain the proper lock for the VM system */
758
759     AFS_GLOCK();
760     afs_InitReq(&treq, cred);
761     code = afs_VerifyVCache(avc, &treq);
762     if (code) {
763         *pl = VM_PAGE_NULL;
764         code = afs_CheckCode(code, &treq, 39); /* failed to get it */
765         AFS_GUNLOCK();
766         return code;
767     }
768         
769     /* clean all dirty pages for this vnode */
770     AFS_GUNLOCK();
771     ubc_flush_dirty(vop,0);
772     AFS_GLOCK();
773
774     afs_BozonLock(&avc->pvnLock, avc);
775     ObtainWriteLock(&avc->lock,167);
776     afs_Trace4(afs_iclSetp, CM_TRACE_PAGEIN, ICL_TYPE_POINTER, avc,
777                ICL_TYPE_LONG, offset, ICL_TYPE_LONG, len,
778                ICL_TYPE_INT32, (int) rw);
779     for (i = 0; i < pages; i++) {
780         pagep = &pl[i];
781         off = offset + PAGE_SIZE * i;
782         if (protp) protp[i] = 0;
783         flags = 0;
784         ReleaseWriteLock(&avc->lock);
785         AFS_GUNLOCK();
786         code = ubc_lookup(((struct vnode *)avc)->v_object, off,
787                         PAGE_SIZE, PAGE_SIZE, pagep, &flags);
788         AFS_GLOCK();
789         ObtainWriteLock(&avc->lock,168);
790         if (code) {
791             goto out;
792         }
793         if(flags & B_NOCACHE) {         /* if (page) */
794             if ((rw & B_WRITE) && (offset+len >= avc->m.Length)) {
795                 struct vnode *vp = (struct vnode *)avc;
796                 /* we're doing a write operation past eof; no need to read it */
797                 AFS_GUNLOCK();
798                 ubc_page_zero(*pagep, 0, PAGE_SIZE);
799                 ubc_page_release(*pagep, B_DONE);
800                 AFS_GLOCK();
801             } else {
802                 /* page wasn't cached, read it in. */
803                 struct buf *bp;
804
805                 AFS_GUNLOCK();
806                 bp = ubc_bufalloc(*pagep, 1, PAGE_SIZE, 1, B_READ);
807                 AFS_GLOCK();
808                 bp->b_dev = 0;
809                 bp->b_vp = (struct vnode *)avc;
810                 bp->b_blkno = btodb(off);
811                 ReleaseWriteLock(&avc->lock);
812                 code = afs_ustrategy(bp, cred); /* do the I/O */
813                 ObtainWriteLock(&avc->lock,169);
814                 AFS_GUNLOCK();
815                 ubc_sync_iodone(bp);
816                 AFS_GLOCK();
817                 if (code) {
818                     AFS_GUNLOCK();
819                     ubc_page_release(pl[i], 0);
820                     AFS_GLOCK();
821                     goto out;
822                 }
823             }
824         }
825         if ((rw & B_READ) == 0) {
826             AFS_GUNLOCK();
827             ubc_page_dirty(pl[i]);
828             AFS_GLOCK();
829         } else {
830             if (protp && (flags & B_DIRTY) == 0) {
831                 protp[i] = VM_PROT_WRITE;
832             }
833         }
834     }
835 out:
836     pl[i] = VM_PAGE_NULL;
837     ReleaseWriteLock(&avc->lock);
838     afs_BozonUnlock(&avc->pvnLock, avc);
839     afs_Trace3(afs_iclSetp, CM_TRACE_PAGEINDONE, ICL_TYPE_INT32, code,
840                ICL_TYPE_POINTER, *pagep, ICL_TYPE_INT32, flags);
841     code = afs_CheckCode(code, &treq, 40);
842     AFS_GUNLOCK();
843     return code;
844 }
845
846
847 int mp_afs_putpage(vop, pl, pcnt, flags, cred)
848     vm_ubc_object_t vop;
849     vm_page_t *pl;
850     int pcnt;
851     int flags;
852     struct ucred *cred;
853 {
854     register afs_int32 code=0;
855     struct vcache *avc = (struct vcache *)vop->vu_vp;
856     struct vnode *vp = (struct vnode *)avc;
857     int i;
858
859     AFS_GLOCK();
860     afs_Trace4(afs_iclSetp, CM_TRACE_PAGEOUT, ICL_TYPE_POINTER, avc,
861                ICL_TYPE_INT32, pcnt, ICL_TYPE_INT32, vp->v_flag,
862                ICL_TYPE_INT32, flags);
863     if (flags & B_UBC) {
864         AFS_GUNLOCK();
865         VN_LOCK(vp);
866         if (vp->v_flag & VXLOCK) {
867             VN_UNLOCK(vp);
868             for (i = 0; i < pcnt; i++) {
869                 ubc_page_release(pl[i], B_DONE|B_DIRTY);
870                 pl[i] = VM_PAGE_NULL;
871             }
872             return(0);
873         } else {
874             VN_UNLOCK(vp);
875         }
876         AFS_GLOCK();
877     }
878
879     /* first, obtain the proper lock for the VM system */
880     afs_BozonLock(&avc->pvnLock, avc);
881     ObtainWriteLock(&avc->lock,170);
882     for (i = 0; i < pcnt; i++) {
883         vm_page_t page = pl[i];
884         struct buf *bp;
885
886         /* write it out */
887         AFS_GUNLOCK();
888         bp = ubc_bufalloc(page, 1, PAGE_SIZE, 1, B_WRITE);
889         AFS_GLOCK();
890         bp->b_dev = 0;
891         bp->b_vp = (struct vnode *)avc;
892         bp->b_blkno = btodb(page->pg_offset);
893         ReleaseWriteLock(&avc->lock);
894         code = afs_ustrategy(bp, cred); /* do the I/O */
895         ObtainWriteLock(&avc->lock,171);
896         AFS_GUNLOCK();
897         ubc_sync_iodone(bp);
898         AFS_GLOCK();
899         if (code) {
900             goto done;
901         } else {
902             pl[i] = VM_PAGE_NULL;
903         }
904     }
905 done:
906     ReleaseWriteLock(&avc->lock);
907     afs_BozonUnlock(&avc->pvnLock, avc);
908     afs_Trace2(afs_iclSetp, CM_TRACE_PAGEOUTDONE, ICL_TYPE_INT32, code,
909                ICL_TYPE_INT32, avc->m.Length);
910     AFS_GUNLOCK();
911     return code;
912 }
913
914
915 int mp_afs_swap(avc, swapop, argp)
916     struct vcache *avc;
917     vp_swap_op_t swapop;
918     vm_offset_t argp;
919 {
920     return EIO;
921 }
922
923 int mp_afs_syncdata(avc, flag, offset, length, cred)
924     struct vcache *avc;
925     int flag;
926     vm_offset_t offset;
927     vm_size_t length;
928     struct ucred *cred;
929 {
930     /* NFS V3 makes this call, ignore it. We'll sync the data in afs_fsync. */
931     if (AFS_NFSXLATORREQ(cred))
932         return 0;
933     else
934         return EINVAL;
935 }
936
937 /* a freelist of one */
938 struct buf *afs_bread_freebp = 0;
939
940 /*
941  *  Only rfs_read calls this, and it only looks at bp->b_un.b_addr.
942  *  Thus we can use fake bufs (ie not from the real buffer pool).
943  */
944 mp_afs_bread(vp, lbn, bpp, cred)
945         struct ucred *cred;
946         struct vnode *vp;
947         daddr_t lbn;
948         struct buf **bpp;
949 {
950         int offset, fsbsize, error;
951         struct buf *bp;
952         struct iovec iov;
953         struct uio uio;
954
955         AFS_GLOCK();
956         AFS_STATCNT(afs_bread);
957         fsbsize = vp->v_vfsp->vfs_bsize;
958         offset = lbn * fsbsize;
959         if (afs_bread_freebp) {
960                 bp = afs_bread_freebp;
961                 afs_bread_freebp = 0;
962         } else {
963                 bp = (struct buf *) AFS_KALLOC(sizeof(*bp));
964                 bp->b_un.b_addr = (caddr_t) AFS_KALLOC(fsbsize);
965         }
966
967         iov.iov_base = bp->b_un.b_addr;
968         iov.iov_len = fsbsize;
969         uio.afsio_iov = &iov;
970         uio.afsio_iovcnt = 1;
971         uio.afsio_seg = AFS_UIOSYS;
972         uio.afsio_offset = offset;
973         uio.afsio_resid = fsbsize;
974         *bpp = 0;
975         error = afs_read((struct vcache *)vp, &uio, cred, lbn, bpp, 0);
976         if (error) {
977                 afs_bread_freebp = bp;
978                 AFS_GUNLOCK();
979                 return error;
980         }
981         if (*bpp) {
982                 afs_bread_freebp = bp;
983         } else {
984                 *(struct buf **)&bp->b_vp = bp; /* mark as fake */
985                 *bpp = bp;
986         }
987         AFS_GUNLOCK();
988         return 0;
989 }
990
991
992 mp_afs_brelse(vp, bp)
993 struct vnode *vp;
994 struct buf *bp;
995 {
996     AFS_GLOCK();
997     AFS_STATCNT(afs_brelse);
998         if ((struct buf *)bp->b_vp != bp) { /* not fake */
999             brelse(bp);
1000         } else if (afs_bread_freebp) {
1001                 AFS_KFREE(bp->b_un.b_addr, vp->v_vfsp->vfs_bsize);
1002                 AFS_KFREE(bp, sizeof(*bp));
1003         } else {
1004                 afs_bread_freebp = bp;
1005         }
1006     AFS_GUNLOCK();
1007 }
1008
1009
1010 mp_afs_bmap(avc, abn, anvp, anbn)
1011     register struct vcache *avc;
1012     afs_int32 abn, *anbn;
1013     struct vcache **anvp;
1014 {
1015     AFS_GLOCK();
1016     AFS_STATCNT(afs_bmap);
1017     if (anvp)
1018         *anvp = avc;
1019     if (anbn)
1020         *anbn = abn * (8192 / DEV_BSIZE);   /* in 512 byte units */
1021     AFS_GUNLOCK();
1022     return 0;
1023 }
1024
1025
1026 /* real strategy */
1027 mp_afs_strategy (abp)
1028     register struct buf *abp;
1029 {
1030     register afs_int32 code;
1031
1032     AFS_GLOCK();
1033     AFS_STATCNT(afs_strategy);
1034     code = afs_osi_MapStrategy(afs_ustrategy, abp);
1035     AFS_GUNLOCK();
1036     return code;
1037 }
1038
1039
1040 mp_afs_refer(vm_ubc_object_t vop)
1041 {
1042         VREF(vop->vu_vp);
1043 }
1044
1045
1046 mp_afs_release(vm_ubc_object_t vop)
1047 {
1048         vrele(vop->vu_vp);
1049 }
1050
1051
1052 mp_afs_write_check(vm_ubc_object_t vop, vm_page_t pp)
1053 {
1054         return TRUE;
1055 }
1056
1057
1058
1059 struct vfs_ubcops afs_ubcops = {
1060         mp_afs_refer,              /* refer vnode */
1061         mp_afs_release,            /* release vnode */
1062         mp_afs_getpage,            /* get page */
1063         mp_afs_putpage,            /* put page */
1064         mp_afs_write_check,        /* check writablity */
1065 };
1066 #endif /* 0 */
1067
1068 /*
1069  * Cover function for lookup name using OSF equivalent, namei()
1070  *
1071  * Note, the result vnode (ni_vp) in the namei data structure is remains
1072  * locked after return.
1073  */
1074 lookupname(namep, seg, follow, dvpp, cvpp)
1075     char *namep;                /* path name */
1076     int seg;            /* address space containing name */
1077     int follow;         /* follow symbolic links */
1078     struct vnode **dvpp;        /* result, containing parent vnode */
1079     struct vnode **cvpp;        /* result, containing final component vnode */
1080 {
1081     /* Should I use free-bee in u-area? */
1082     struct nameidata *ndp = &u.u_nd;
1083     int error;
1084
1085     ndp->ni_nameiop = ((follow) ? (LOOKUP|FOLLOW) : (LOOKUP));
1086     ndp->ni_segflg = seg;
1087     ndp->ni_dirp = namep;
1088     error = namei(ndp);
1089     if (dvpp != (struct vnode **)0)
1090         *dvpp = ndp->ni_dvp;
1091     if (cvpp != (struct vnode **)0)
1092         *cvpp = ndp->ni_vp;
1093     return(error);
1094 }
1095