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