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