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