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