]> git.saurik.com Git - apple/xnu.git/blob - bsd/kern/ubc_subr.c
xnu-344.21.74.tar.gz
[apple/xnu.git] / bsd / kern / ubc_subr.c
1 /*
2 * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /*
26 * File: ubc_subr.c
27 * Author: Umesh Vaishampayan [umeshv@apple.com]
28 * 05-Aug-1999 umeshv Created.
29 *
30 * Functions related to Unified Buffer cache.
31 *
32 * Caller of UBC functions MUST have a valid reference on the vnode.
33 *
34 */
35
36 #undef DIAGNOSTIC
37 #define DIAGNOSTIC 1
38
39 #include <sys/types.h>
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/lock.h>
43 #include <sys/ubc.h>
44 #include <sys/mount.h>
45 #include <sys/vnode.h>
46 #include <sys/ubc.h>
47 #include <sys/ucred.h>
48 #include <sys/proc.h>
49 #include <sys/buf.h>
50
51 #include <mach/mach_types.h>
52 #include <mach/memory_object_types.h>
53
54 #include <kern/zalloc.h>
55
56 #if DIAGNOSTIC
57 #if defined(assert)
58 #undef assert()
59 #endif
60 #define assert(cond) \
61 ((void) ((cond) ? 0 : panic("%s:%d (%s)", __FILE__, __LINE__, # cond)))
62 #else
63 #include <kern/assert.h>
64 #endif /* DIAGNOSTIC */
65
66 struct zone *ubc_info_zone;
67
68 /* lock for changes to struct UBC */
69 static __inline__ void
70 ubc_lock(struct vnode *vp)
71 {
72 /* For now, just use the v_interlock */
73 simple_lock(&vp->v_interlock);
74 }
75
76 /* unlock */
77 static __inline__ void
78 ubc_unlock(struct vnode *vp)
79 {
80 /* For now, just use the v_interlock */
81 simple_unlock(&vp->v_interlock);
82 }
83
84 /*
85 * Serialize the requests to the VM
86 * Returns:
87 * 0 - Failure
88 * 1 - Sucessful in acquiring the lock
89 * 2 - Sucessful in acquiring the lock recursively
90 * do not call ubc_unbusy()
91 * [This is strange, but saves 4 bytes in struct ubc_info]
92 */
93 static int
94 ubc_busy(struct vnode *vp)
95 {
96 register struct ubc_info *uip;
97
98 if (!UBCINFOEXISTS(vp))
99 return (0);
100
101 uip = vp->v_ubcinfo;
102
103 while (ISSET(uip->ui_flags, UI_BUSY)) {
104
105 if (uip->ui_owner == (void *)current_thread())
106 return (2);
107
108 SET(uip->ui_flags, UI_WANTED);
109 (void) tsleep((caddr_t)&vp->v_ubcinfo, PINOD, "ubcbusy", 0);
110
111 if (!UBCINFOEXISTS(vp))
112 return (0);
113 }
114 uip->ui_owner = (void *)current_thread();
115
116 SET(uip->ui_flags, UI_BUSY);
117
118 return (1);
119 }
120
121 static void
122 ubc_unbusy(struct vnode *vp)
123 {
124 register struct ubc_info *uip;
125
126 if (!UBCINFOEXISTS(vp)) {
127 wakeup((caddr_t)&vp->v_ubcinfo);
128 return;
129 }
130 uip = vp->v_ubcinfo;
131 CLR(uip->ui_flags, UI_BUSY);
132 uip->ui_owner = (void *)NULL;
133
134 if (ISSET(uip->ui_flags, UI_WANTED)) {
135 CLR(uip->ui_flags, UI_WANTED);
136 wakeup((caddr_t)&vp->v_ubcinfo);
137 }
138 }
139
140 /*
141 * Initialization of the zone for Unified Buffer Cache.
142 */
143 __private_extern__ void
144 ubc_init()
145 {
146 int i;
147
148 i = (vm_size_t) sizeof (struct ubc_info);
149 /* XXX the number of elements should be tied in to maxvnodes */
150 ubc_info_zone = zinit (i, 10000*i, 8192, "ubc_info zone");
151 return;
152 }
153
154 /*
155 * Initialize a ubc_info structure for a vnode.
156 */
157 int
158 ubc_info_init(struct vnode *vp)
159 {
160 register struct ubc_info *uip;
161 void * pager;
162 struct vattr vattr;
163 struct proc *p = current_proc();
164 int error = 0;
165 kern_return_t kret;
166 memory_object_control_t control;
167
168 if (!UBCISVALID(vp))
169 return (EINVAL);
170
171 ubc_lock(vp);
172 if (ISSET(vp->v_flag, VUINIT)) {
173 /*
174 * other thread is already doing this
175 * wait till done
176 */
177 while (ISSET(vp->v_flag, VUINIT)) {
178 SET(vp->v_flag, VUWANT); /* XXX overloaded! */
179 ubc_unlock(vp);
180 (void) tsleep((caddr_t)vp, PINOD, "ubcinfo", 0);
181 ubc_lock(vp);
182 }
183 ubc_unlock(vp);
184 return (0);
185 } else {
186 SET(vp->v_flag, VUINIT);
187 }
188
189 uip = vp->v_ubcinfo;
190 if ((uip == UBC_INFO_NULL) || (uip == UBC_NOINFO)) {
191 ubc_unlock(vp);
192 uip = (struct ubc_info *) zalloc(ubc_info_zone);
193 uip->ui_pager = MEMORY_OBJECT_NULL;
194 uip->ui_control = MEMORY_OBJECT_CONTROL_NULL;
195 uip->ui_flags = UI_INITED;
196 uip->ui_vnode = vp;
197 uip->ui_ucred = NOCRED;
198 uip->ui_refcount = 1;
199 uip->ui_size = 0;
200 uip->ui_mapped = 0;
201 uip->ui_owner = (void *)NULL;
202 ubc_lock(vp);
203 }
204 #if DIAGNOSTIC
205 else
206 Debugger("ubc_info_init: already");
207 #endif /* DIAGNOSTIC */
208
209 assert(uip->ui_flags != UI_NONE);
210 assert(uip->ui_vnode == vp);
211
212 #if 0
213 if(ISSET(uip->ui_flags, UI_HASPAGER))
214 goto done;
215 #endif /* 0 */
216
217 /* now set this ubc_info in the vnode */
218 vp->v_ubcinfo = uip;
219 SET(uip->ui_flags, UI_HASPAGER);
220 ubc_unlock(vp);
221 pager = (void *)vnode_pager_setup(vp, uip->ui_pager);
222 assert(pager);
223 ubc_setpager(vp, pager);
224
225 /*
226 * Note: We can not use VOP_GETATTR() to get accurate
227 * value of ui_size. Thanks to NFS.
228 * nfs_getattr() can call vinvalbuf() and in this case
229 * ubc_info is not set up to deal with that.
230 * So use bogus size.
231 */
232
233 /*
234 * create a vnode - vm_object association
235 * memory_object_create_named() creates a "named" reference on the
236 * memory object we hold this reference as long as the vnode is
237 * "alive." Since memory_object_create_named() took its own reference
238 * on the vnode pager we passed it, we can drop the reference
239 * vnode_pager_setup() returned here.
240 */
241 kret = memory_object_create_named(pager,
242 (memory_object_size_t)uip->ui_size, &control);
243 vnode_pager_deallocate(pager);
244 if (kret != KERN_SUCCESS)
245 panic("ubc_info_init: memory_object_create_named returned %d", kret);
246
247 assert(control);
248 uip->ui_control = control; /* cache the value of the mo control */
249 SET(uip->ui_flags, UI_HASOBJREF); /* with a named reference */
250 /* create a pager reference on the vnode */
251 error = vnode_pager_vget(vp);
252 if (error)
253 panic("ubc_info_init: vnode_pager_vget error = %d", error);
254
255 /* initialize the size */
256 error = VOP_GETATTR(vp, &vattr, p->p_ucred, p);
257
258 ubc_lock(vp);
259 uip->ui_size = (error ? 0: vattr.va_size);
260
261 done:
262 CLR(vp->v_flag, VUINIT);
263 if (ISSET(vp->v_flag, VUWANT)) {
264 CLR(vp->v_flag, VUWANT);
265 ubc_unlock(vp);
266 wakeup((caddr_t)vp);
267 } else
268 ubc_unlock(vp);
269
270 return (error);
271 }
272
273 /* Free the ubc_info */
274 static void
275 ubc_info_free(struct ubc_info *uip)
276 {
277 struct ucred *credp;
278
279 credp = uip->ui_ucred;
280 if (credp != NOCRED) {
281 uip->ui_ucred = NOCRED;
282 crfree(credp);
283 }
284
285 if (uip->ui_control != MEMORY_OBJECT_CONTROL_NULL)
286 memory_object_control_deallocate(uip->ui_control);
287
288 zfree(ubc_info_zone, (vm_offset_t)uip);
289 return;
290 }
291
292 void
293 ubc_info_deallocate(struct ubc_info *uip)
294 {
295
296 assert(uip->ui_refcount > 0);
297
298 if (uip->ui_refcount-- == 1) {
299 struct vnode *vp;
300
301 vp = uip->ui_vnode;
302 if (ISSET(uip->ui_flags, UI_WANTED)) {
303 CLR(uip->ui_flags, UI_WANTED);
304 wakeup((caddr_t)&vp->v_ubcinfo);
305 }
306
307 ubc_info_free(uip);
308 }
309 }
310
311 /*
312 * Communicate with VM the size change of the file
313 * returns 1 on success, 0 on failure
314 */
315 int
316 ubc_setsize(struct vnode *vp, off_t nsize)
317 {
318 off_t osize; /* ui_size before change */
319 off_t lastpg, olastpgend, lastoff;
320 struct ubc_info *uip;
321 memory_object_control_t control;
322 kern_return_t kret;
323
324 assert(nsize >= (off_t)0);
325
326 if (UBCINVALID(vp))
327 return (0);
328
329 if (!UBCINFOEXISTS(vp))
330 return (0);
331
332 uip = vp->v_ubcinfo;
333 osize = uip->ui_size; /* call ubc_getsize() ??? */
334 /* Update the size before flushing the VM */
335 uip->ui_size = nsize;
336
337 if (nsize >= osize) /* Nothing more to do */
338 return (1); /* return success */
339
340 /*
341 * When the file shrinks, invalidate the pages beyond the
342 * new size. Also get rid of garbage beyond nsize on the
343 * last page. The ui_size already has the nsize. This
344 * insures that the pageout would not write beyond the new
345 * end of the file.
346 */
347
348 lastpg = trunc_page_64(nsize);
349 olastpgend = round_page_64(osize);
350 control = uip->ui_control;
351 assert(control);
352 lastoff = (nsize & PAGE_MASK_64);
353
354 /*
355 * If length is multiple of page size, we should not flush
356 * invalidating is sufficient
357 */
358 if (!lastoff) {
359 /* invalidate last page and old contents beyond nsize */
360 kret = memory_object_lock_request(control,
361 (memory_object_offset_t)lastpg,
362 (memory_object_size_t)(olastpgend - lastpg),
363 MEMORY_OBJECT_RETURN_NONE, MEMORY_OBJECT_DATA_FLUSH,
364 VM_PROT_NO_CHANGE);
365 if (kret != KERN_SUCCESS)
366 printf("ubc_setsize: invalidate failed (error = %d)\n", kret);
367
368 return ((kret == KERN_SUCCESS) ? 1 : 0);
369 }
370
371 /* flush the last page */
372 kret = memory_object_lock_request(control,
373 (memory_object_offset_t)lastpg,
374 PAGE_SIZE_64,
375 MEMORY_OBJECT_RETURN_DIRTY, FALSE,
376 VM_PROT_NO_CHANGE);
377
378 if (kret == KERN_SUCCESS) {
379 /* invalidate last page and old contents beyond nsize */
380 kret = memory_object_lock_request(control,
381 (memory_object_offset_t)lastpg,
382 (memory_object_size_t)(olastpgend - lastpg),
383 MEMORY_OBJECT_RETURN_NONE, MEMORY_OBJECT_DATA_FLUSH,
384 VM_PROT_NO_CHANGE);
385 if (kret != KERN_SUCCESS)
386 printf("ubc_setsize: invalidate failed (error = %d)\n", kret);
387 } else
388 printf("ubc_setsize: flush failed (error = %d)\n", kret);
389
390 return ((kret == KERN_SUCCESS) ? 1 : 0);
391 }
392
393 /*
394 * Get the size of the file
395 */
396 off_t
397 ubc_getsize(struct vnode *vp)
398 {
399 return (vp->v_ubcinfo->ui_size);
400 }
401
402 /*
403 * Caller indicate that the object corresponding to the vnode
404 * can not be cached in object cache. Make it so.
405 * returns 1 on success, 0 on failure
406 */
407 int
408 ubc_uncache(struct vnode *vp)
409 {
410 kern_return_t kret;
411 struct ubc_info *uip;
412 int recursed;
413 memory_object_control_t control;
414 memory_object_perf_info_data_t perf;
415
416 if (!UBCINFOEXISTS(vp))
417 return (0);
418
419 if ((recursed = ubc_busy(vp)) == 0)
420 return (0);
421
422 uip = vp->v_ubcinfo;
423
424 assert(uip != UBC_INFO_NULL);
425
426 /*
427 * AGE it so that vfree() can make sure that it
428 * would get recycled soon after the last reference is gone
429 * This will insure that .nfs turds would not linger
430 */
431 vagevp(vp);
432
433 /* set the "do not cache" bit */
434 SET(uip->ui_flags, UI_DONTCACHE);
435
436 control = uip->ui_control;
437 assert(control);
438
439 perf.cluster_size = PAGE_SIZE; /* XXX use real cluster_size. */
440 perf.may_cache = FALSE;
441 kret = memory_object_change_attributes(control,
442 MEMORY_OBJECT_PERFORMANCE_INFO,
443 (memory_object_info_t) &perf,
444 MEMORY_OBJECT_PERF_INFO_COUNT);
445
446 if (kret != KERN_SUCCESS) {
447 printf("ubc_uncache: memory_object_change_attributes_named "
448 "kret = %d", kret);
449 if (recursed == 1)
450 ubc_unbusy(vp);
451 return (0);
452 }
453
454 ubc_release_named(vp);
455
456 if (recursed == 1)
457 ubc_unbusy(vp);
458 return (1);
459 }
460
461 /*
462 * call ubc_clean() and ubc_uncache() on all the vnodes
463 * for this mount point.
464 * returns 1 on success, 0 on failure
465 */
466 __private_extern__ int
467 ubc_umount(struct mount *mp)
468 {
469 struct proc *p = current_proc();
470 struct vnode *vp, *nvp;
471 int ret = 1;
472
473 loop:
474 simple_lock(&mntvnode_slock);
475 for (vp = mp->mnt_vnodelist.lh_first; vp; vp = nvp) {
476 if (vp->v_mount != mp) {
477 simple_unlock(&mntvnode_slock);
478 goto loop;
479 }
480 nvp = vp->v_mntvnodes.le_next;
481 simple_unlock(&mntvnode_slock);
482 if (UBCINFOEXISTS(vp)) {
483
484 /*
485 * Must get a valid reference on the vnode
486 * before callig UBC functions
487 */
488 if (vget(vp, 0, p)) {
489 ret = 0;
490 simple_lock(&mntvnode_slock);
491 continue; /* move on to the next vnode */
492 }
493 ret &= ubc_clean(vp, 0); /* do not invalidate */
494 ret &= ubc_uncache(vp);
495 vrele(vp);
496 }
497 simple_lock(&mntvnode_slock);
498 }
499 simple_unlock(&mntvnode_slock);
500 return (ret);
501 }
502
503 /*
504 * Call ubc_unmount() for all filesystems.
505 * The list is traversed in reverse order
506 * of mounting to avoid dependencies.
507 */
508 __private_extern__ void
509 ubc_unmountall()
510 {
511 struct mount *mp, *nmp;
512
513 /*
514 * Since this only runs when rebooting, it is not interlocked.
515 */
516 for (mp = mountlist.cqh_last; mp != (void *)&mountlist; mp = nmp) {
517 nmp = mp->mnt_list.cqe_prev;
518 (void) ubc_umount(mp);
519 }
520 }
521
522 /* Get the credentials */
523 struct ucred *
524 ubc_getcred(struct vnode *vp)
525 {
526 struct ubc_info *uip;
527
528 uip = vp->v_ubcinfo;
529
530 if (UBCINVALID(vp))
531 return (NOCRED);
532
533 return (uip->ui_ucred);
534 }
535
536 /*
537 * Set the credentials
538 * existing credentials are not changed
539 * returns 1 on success and 0 on failure
540 */
541 int
542 ubc_setcred(struct vnode *vp, struct proc *p)
543 {
544 struct ubc_info *uip;
545 struct ucred *credp;
546
547 uip = vp->v_ubcinfo;
548
549 if (UBCINVALID(vp))
550 return (0);
551
552 credp = uip->ui_ucred;
553 if (credp == NOCRED) {
554 crhold(p->p_ucred);
555 uip->ui_ucred = p->p_ucred;
556 }
557
558 return (1);
559 }
560
561 /* Get the pager */
562 __private_extern__ memory_object_t
563 ubc_getpager(struct vnode *vp)
564 {
565 struct ubc_info *uip;
566
567 uip = vp->v_ubcinfo;
568
569 if (UBCINVALID(vp))
570 return (0);
571
572 return (uip->ui_pager);
573 }
574
575 /*
576 * Get the memory object associated with this vnode
577 * If the vnode was reactivated, memory object would not exist.
578 * Unless "do not rectivate" was specified, look it up using the pager.
579 * If hold was requested create an object reference of one does not
580 * exist already.
581 */
582
583 memory_object_control_t
584 ubc_getobject(struct vnode *vp, int flags)
585 {
586 struct ubc_info *uip;
587 int recursed;
588 memory_object_control_t control;
589
590 if (UBCINVALID(vp))
591 return (0);
592
593 if (flags & UBC_FOR_PAGEOUT)
594 return(vp->v_ubcinfo->ui_control);
595
596 if ((recursed = ubc_busy(vp)) == 0)
597 return (0);
598
599 uip = vp->v_ubcinfo;
600 control = uip->ui_control;
601
602 if ((flags & UBC_HOLDOBJECT) && (!ISSET(uip->ui_flags, UI_HASOBJREF))) {
603
604 /*
605 * Take a temporary reference on the ubc info so that it won't go
606 * away during our recovery attempt.
607 */
608 ubc_lock(vp);
609 uip->ui_refcount++;
610 ubc_unlock(vp);
611 if (memory_object_recover_named(control, TRUE) == KERN_SUCCESS) {
612 SET(uip->ui_flags, UI_HASOBJREF);
613 } else {
614 control = MEMORY_OBJECT_CONTROL_NULL;
615 }
616 if (recursed == 1)
617 ubc_unbusy(vp);
618 ubc_info_deallocate(uip);
619
620 } else {
621 if (recursed == 1)
622 ubc_unbusy(vp);
623 }
624
625 return (control);
626 }
627
628 /* Set the pager */
629 int
630 ubc_setpager(struct vnode *vp, memory_object_t pager)
631 {
632 struct ubc_info *uip;
633
634 uip = vp->v_ubcinfo;
635
636 if (UBCINVALID(vp))
637 return (0);
638
639 uip->ui_pager = pager;
640 return (1);
641 }
642
643 int
644 ubc_setflags(struct vnode * vp, int flags)
645 {
646 struct ubc_info *uip;
647
648 if (UBCINVALID(vp))
649 return (0);
650
651 uip = vp->v_ubcinfo;
652
653 SET(uip->ui_flags, flags);
654
655 return (1);
656 }
657
658 int
659 ubc_clearflags(struct vnode * vp, int flags)
660 {
661 struct ubc_info *uip;
662
663 if (UBCINVALID(vp))
664 return (0);
665
666 uip = vp->v_ubcinfo;
667
668 CLR(uip->ui_flags, flags);
669
670 return (1);
671 }
672
673
674 int
675 ubc_issetflags(struct vnode * vp, int flags)
676 {
677 struct ubc_info *uip;
678
679 if (UBCINVALID(vp))
680 return (0);
681
682 uip = vp->v_ubcinfo;
683
684 return (ISSET(uip->ui_flags, flags));
685 }
686
687 off_t
688 ubc_blktooff(struct vnode *vp, daddr_t blkno)
689 {
690 off_t file_offset;
691 int error;
692
693 if (UBCINVALID(vp))
694 return ((off_t)-1);
695
696 error = VOP_BLKTOOFF(vp, blkno, &file_offset);
697 if (error)
698 file_offset = -1;
699
700 return (file_offset);
701 }
702
703 daddr_t
704 ubc_offtoblk(struct vnode *vp, off_t offset)
705 {
706 daddr_t blkno;
707 int error = 0;
708
709 if (UBCINVALID(vp)) {
710 return ((daddr_t)-1);
711 }
712
713 error = VOP_OFFTOBLK(vp, offset, &blkno);
714 if (error)
715 blkno = -1;
716
717 return (blkno);
718 }
719
720 /*
721 * Cause the file data in VM to be pushed out to the storage
722 * it also causes all currently valid pages to be released
723 * returns 1 on success, 0 on failure
724 */
725 int
726 ubc_clean(struct vnode *vp, int invalidate)
727 {
728 off_t size;
729 struct ubc_info *uip;
730 memory_object_control_t control;
731 kern_return_t kret;
732 int flags = 0;
733
734 if (UBCINVALID(vp))
735 return (0);
736
737 if (!UBCINFOEXISTS(vp))
738 return (0);
739
740 /*
741 * if invalidate was requested, write dirty data and then discard
742 * the resident pages
743 */
744 if (invalidate)
745 flags = (MEMORY_OBJECT_DATA_FLUSH | MEMORY_OBJECT_DATA_NO_CHANGE);
746
747 uip = vp->v_ubcinfo;
748 size = uip->ui_size; /* call ubc_getsize() ??? */
749
750 control = uip->ui_control;
751 assert(control);
752
753 vp->v_flag &= ~VHASDIRTY;
754 vp->v_clen = 0;
755
756 /* Write the dirty data in the file and discard cached pages */
757 kret = memory_object_lock_request(control,
758 (memory_object_offset_t)0,
759 (memory_object_size_t)round_page_64(size),
760 MEMORY_OBJECT_RETURN_ALL, flags,
761 VM_PROT_NO_CHANGE);
762
763 if (kret != KERN_SUCCESS)
764 printf("ubc_clean: clean failed (error = %d)\n", kret);
765
766 return ((kret == KERN_SUCCESS) ? 1 : 0);
767 }
768
769 /*
770 * Cause the file data in VM to be pushed out to the storage
771 * currently valid pages are NOT invalidated
772 * returns 1 on success, 0 on failure
773 */
774 int
775 ubc_pushdirty(struct vnode *vp)
776 {
777 off_t size;
778 struct ubc_info *uip;
779 memory_object_control_t control;
780 kern_return_t kret;
781
782 if (UBCINVALID(vp))
783 return (0);
784
785 if (!UBCINFOEXISTS(vp))
786 return (0);
787
788 uip = vp->v_ubcinfo;
789 size = uip->ui_size; /* call ubc_getsize() ??? */
790
791 control = uip->ui_control;
792 assert(control);
793
794 vp->v_flag &= ~VHASDIRTY;
795 vp->v_clen = 0;
796
797 /* Write the dirty data in the file and discard cached pages */
798 kret = memory_object_lock_request(control,
799 (memory_object_offset_t)0,
800 (memory_object_size_t)round_page_64(size),
801 MEMORY_OBJECT_RETURN_DIRTY, FALSE,
802 VM_PROT_NO_CHANGE);
803
804 if (kret != KERN_SUCCESS)
805 printf("ubc_pushdirty: flush failed (error = %d)\n", kret);
806
807 return ((kret == KERN_SUCCESS) ? 1 : 0);
808 }
809
810 /*
811 * Cause the file data in VM to be pushed out to the storage
812 * currently valid pages are NOT invalidated
813 * returns 1 on success, 0 on failure
814 */
815 int
816 ubc_pushdirty_range(struct vnode *vp, off_t offset, off_t size)
817 {
818 struct ubc_info *uip;
819 memory_object_control_t control;
820 kern_return_t kret;
821
822 if (UBCINVALID(vp))
823 return (0);
824
825 if (!UBCINFOEXISTS(vp))
826 return (0);
827
828 uip = vp->v_ubcinfo;
829
830 control = uip->ui_control;
831 assert(control);
832
833 /* Write any dirty pages in the requested range of the file: */
834 kret = memory_object_lock_request(control,
835 (memory_object_offset_t)offset,
836 (memory_object_size_t)round_page_64(size),
837 MEMORY_OBJECT_RETURN_DIRTY, FALSE,
838 VM_PROT_NO_CHANGE);
839
840 if (kret != KERN_SUCCESS)
841 printf("ubc_pushdirty_range: flush failed (error = %d)\n", kret);
842
843 return ((kret == KERN_SUCCESS) ? 1 : 0);
844 }
845
846 /*
847 * Make sure the vm object does not vanish
848 * returns 1 if the hold count was incremented
849 * returns 0 if the hold count was not incremented
850 * This return value should be used to balance
851 * ubc_hold() and ubc_rele().
852 */
853 int
854 ubc_hold(struct vnode *vp)
855 {
856 struct ubc_info *uip;
857 int recursed;
858 memory_object_control_t object;
859
860 if (UBCINVALID(vp))
861 return (0);
862
863 if ((recursed = ubc_busy(vp)) == 0) {
864 /* must be invalid or dying vnode */
865 assert(UBCINVALID(vp) ||
866 ((vp->v_flag & VXLOCK) || (vp->v_flag & VTERMINATE)));
867 return (0);
868 }
869
870 uip = vp->v_ubcinfo;
871 assert(uip->ui_control != MEMORY_OBJECT_CONTROL_NULL);
872
873 ubc_lock(vp);
874 uip->ui_refcount++;
875 ubc_unlock(vp);
876
877 if (!ISSET(uip->ui_flags, UI_HASOBJREF)) {
878 if (memory_object_recover_named(uip->ui_control, TRUE)
879 != KERN_SUCCESS) {
880 if (recursed == 1)
881 ubc_unbusy(vp);
882 ubc_info_deallocate(uip);
883 return (0);
884 }
885 SET(uip->ui_flags, UI_HASOBJREF);
886 }
887 if (recursed == 1)
888 ubc_unbusy(vp);
889
890 assert(uip->ui_refcount > 0);
891
892 return (1);
893 }
894
895 /*
896 * Drop the holdcount.
897 * release the reference on the vm object if the this is "uncached"
898 * ubc_info.
899 */
900 void
901 ubc_rele(struct vnode *vp)
902 {
903 struct ubc_info *uip;
904
905 if (UBCINVALID(vp))
906 return;
907
908 if (!UBCINFOEXISTS(vp)) {
909 /* nothing more to do for a dying vnode */
910 if ((vp->v_flag & VXLOCK) || (vp->v_flag & VTERMINATE))
911 return;
912 panic("ubc_rele: can not");
913 }
914
915 uip = vp->v_ubcinfo;
916
917 if (uip->ui_refcount == 1)
918 panic("ubc_rele: ui_refcount");
919
920 --uip->ui_refcount;
921
922 if ((uip->ui_refcount == 1)
923 && ISSET(uip->ui_flags, UI_DONTCACHE))
924 (void) ubc_release_named(vp);
925
926 return;
927 }
928
929 /*
930 * The vnode is mapped explicitly, mark it so.
931 */
932 __private_extern__ void
933 ubc_map(struct vnode *vp)
934 {
935 struct ubc_info *uip;
936
937 if (UBCINVALID(vp))
938 return;
939
940 if (!UBCINFOEXISTS(vp))
941 return;
942
943 ubc_lock(vp);
944 uip = vp->v_ubcinfo;
945
946 SET(uip->ui_flags, UI_WASMAPPED);
947 uip->ui_mapped = 1;
948 ubc_unlock(vp);
949
950 return;
951 }
952
953 /*
954 * Release the memory object reference on the vnode
955 * only if it is not in use
956 * Return 1 if the reference was released, 0 otherwise.
957 */
958 int
959 ubc_release_named(struct vnode *vp)
960 {
961 struct ubc_info *uip;
962 int recursed;
963 memory_object_control_t control;
964 kern_return_t kret = KERN_FAILURE;
965
966 if (UBCINVALID(vp))
967 return (0);
968
969 if ((recursed = ubc_busy(vp)) == 0)
970 return (0);
971 uip = vp->v_ubcinfo;
972
973 /* can not release held or mapped vnodes */
974 if (ISSET(uip->ui_flags, UI_HASOBJREF) &&
975 (uip->ui_refcount == 1) && !uip->ui_mapped) {
976 control = uip->ui_control;
977 assert(control);
978 CLR(uip->ui_flags, UI_HASOBJREF);
979 kret = memory_object_release_name(control,
980 MEMORY_OBJECT_RESPECT_CACHE);
981 }
982
983 if (recursed == 1)
984 ubc_unbusy(vp);
985 return ((kret != KERN_SUCCESS) ? 0 : 1);
986 }
987
988 /*
989 * This function used to called by extensions directly. Some may
990 * still exist with this behavior. In those cases, we will do the
991 * release as part of reclaiming or cleaning the vnode. We don't
992 * need anything explicit - so just stub this out until those callers
993 * get cleaned up.
994 */
995 int
996 ubc_release(
997 struct vnode *vp)
998 {
999 return 0;
1000 }
1001
1002 /*
1003 * destroy the named reference for a given vnode
1004 */
1005 __private_extern__ int
1006 ubc_destroy_named(
1007 struct vnode *vp)
1008 {
1009 memory_object_control_t control;
1010 struct proc *p;
1011 struct ubc_info *uip;
1012 kern_return_t kret;
1013
1014 /*
1015 * We may already have had the object terminated
1016 * and the ubcinfo released as a side effect of
1017 * some earlier processing. If so, pretend we did
1018 * it, because it probably was a result of our
1019 * efforts.
1020 */
1021 if (!UBCINFOEXISTS(vp))
1022 return (1);
1023
1024 uip = vp->v_ubcinfo;
1025
1026 /* can not destroy held vnodes */
1027 if (uip->ui_refcount > 1)
1028 return (0);
1029
1030 /*
1031 * Terminate the memory object.
1032 * memory_object_destroy() will result in
1033 * vnode_pager_no_senders().
1034 * That will release the pager reference
1035 * and the vnode will move to the free list.
1036 */
1037 control = ubc_getobject(vp, UBC_HOLDOBJECT);
1038 if (control != MEMORY_OBJECT_CONTROL_NULL) {
1039
1040 if (ISSET(vp->v_flag, VTERMINATE))
1041 panic("ubc_destroy_named: already teminating");
1042 SET(vp->v_flag, VTERMINATE);
1043
1044 kret = memory_object_destroy(control, 0);
1045 if (kret != KERN_SUCCESS)
1046 return (0);
1047
1048 /*
1049 * memory_object_destroy() is asynchronous
1050 * with respect to vnode_pager_no_senders().
1051 * wait for vnode_pager_no_senders() to clear
1052 * VTERMINATE
1053 */
1054 while (ISSET(vp->v_flag, VTERMINATE)) {
1055 SET(vp->v_flag, VTERMWANT);
1056 (void)tsleep((caddr_t)&vp->v_ubcinfo,
1057 PINOD, "ubc_destroy_named", 0);
1058 }
1059 }
1060 return (1);
1061 }
1062
1063
1064 /*
1065 * Invalidate a range in the memory object that backs this
1066 * vnode. The offset is truncated to the page boundary and the
1067 * size is adjusted to include the last page in the range.
1068 */
1069 int
1070 ubc_invalidate(struct vnode *vp, off_t offset, size_t size)
1071 {
1072 struct ubc_info *uip;
1073 memory_object_control_t control;
1074 kern_return_t kret;
1075 off_t toff;
1076 size_t tsize;
1077
1078 if (UBCINVALID(vp))
1079 return (0);
1080
1081 if (!UBCINFOEXISTS(vp))
1082 return (0);
1083
1084 toff = trunc_page_64(offset);
1085 tsize = (size_t)(round_page_64(offset+size) - toff);
1086 uip = vp->v_ubcinfo;
1087 control = uip->ui_control;
1088 assert(control);
1089
1090 /* invalidate pages in the range requested */
1091 kret = memory_object_lock_request(control,
1092 (memory_object_offset_t)toff,
1093 (memory_object_size_t)tsize,
1094 MEMORY_OBJECT_RETURN_NONE,
1095 (MEMORY_OBJECT_DATA_NO_CHANGE| MEMORY_OBJECT_DATA_FLUSH),
1096 VM_PROT_NO_CHANGE);
1097 if (kret != KERN_SUCCESS)
1098 printf("ubc_invalidate: invalidate failed (error = %d)\n", kret);
1099
1100 return ((kret == KERN_SUCCESS) ? 1 : 0);
1101 }
1102
1103 /*
1104 * Find out whether a vnode is in use by UBC
1105 * Returns 1 if file is in use by UBC, 0 if not
1106 */
1107 int
1108 ubc_isinuse(struct vnode *vp, int tookref)
1109 {
1110 int busycount = tookref ? 2 : 1;
1111
1112 if (!UBCINFOEXISTS(vp))
1113 return (0);
1114
1115 if (tookref == 0) {
1116 printf("ubc_isinuse: called without a valid reference"
1117 ": v_tag = %d\v", vp->v_tag);
1118 vprint("ubc_isinuse", vp);
1119 return (0);
1120 }
1121
1122 if (vp->v_usecount > busycount)
1123 return (1);
1124
1125 if ((vp->v_usecount == busycount)
1126 && (vp->v_ubcinfo->ui_mapped == 1))
1127 return (1);
1128 else
1129 return (0);
1130 }
1131
1132 /*
1133 * The backdoor routine to clear the ui_mapped.
1134 * MUST only be called by the VM
1135 *
1136 * Note that this routine is not called under funnel. There are numerous
1137 * things about the calling sequence that make this work on SMP.
1138 * Any code change in those paths can break this.
1139 *
1140 */
1141 __private_extern__ void
1142 ubc_unmap(struct vnode *vp)
1143 {
1144 struct ubc_info *uip;
1145 boolean_t funnel_state;
1146
1147 if (UBCINVALID(vp))
1148 return;
1149
1150 if (!UBCINFOEXISTS(vp))
1151 return;
1152
1153 ubc_lock(vp);
1154 uip = vp->v_ubcinfo;
1155 uip->ui_mapped = 0;
1156 if ((uip->ui_refcount > 1) || !ISSET(uip->ui_flags, UI_DONTCACHE)) {
1157 ubc_unlock(vp);
1158 return;
1159 }
1160 ubc_unlock(vp);
1161
1162 funnel_state = thread_funnel_set(kernel_flock, TRUE);
1163 (void) ubc_release_named(vp);
1164 (void) thread_funnel_set(kernel_flock, funnel_state);
1165 }
1166
1167 kern_return_t
1168 ubc_page_op(
1169 struct vnode *vp,
1170 off_t f_offset,
1171 int ops,
1172 ppnum_t *phys_entryp,
1173 int *flagsp)
1174 {
1175 memory_object_control_t control;
1176
1177 control = ubc_getobject(vp, UBC_FLAGS_NONE);
1178 if (control == MEMORY_OBJECT_CONTROL_NULL)
1179 return KERN_INVALID_ARGUMENT;
1180
1181 return (memory_object_page_op(control,
1182 (memory_object_offset_t)f_offset,
1183 ops,
1184 phys_entryp,
1185 flagsp));
1186 }
1187
1188 kern_return_t
1189 ubc_create_upl(
1190 struct vnode *vp,
1191 off_t f_offset,
1192 long bufsize,
1193 upl_t *uplp,
1194 upl_page_info_t **plp,
1195 int uplflags)
1196 {
1197 memory_object_control_t control;
1198 int count;
1199 int ubcflags;
1200 off_t file_offset;
1201 kern_return_t kr;
1202
1203 if (bufsize & 0xfff)
1204 return KERN_INVALID_ARGUMENT;
1205
1206 if (uplflags & UPL_FOR_PAGEOUT) {
1207 uplflags &= ~UPL_FOR_PAGEOUT;
1208 ubcflags = UBC_FOR_PAGEOUT;
1209 } else
1210 ubcflags = UBC_FLAGS_NONE;
1211
1212 control = ubc_getobject(vp, ubcflags);
1213 if (control == MEMORY_OBJECT_CONTROL_NULL)
1214 return KERN_INVALID_ARGUMENT;
1215
1216 uplflags |= (UPL_NO_SYNC|UPL_CLEAN_IN_PLACE|UPL_SET_INTERNAL);
1217 count = 0;
1218 kr = memory_object_upl_request(control, f_offset, bufsize,
1219 uplp, NULL, &count, uplflags);
1220 if (plp != NULL)
1221 *plp = UPL_GET_INTERNAL_PAGE_LIST(*uplp);
1222 return kr;
1223 }
1224
1225
1226 kern_return_t
1227 ubc_upl_map(
1228 upl_t upl,
1229 vm_offset_t *dst_addr)
1230 {
1231 return (vm_upl_map(kernel_map, upl, dst_addr));
1232 }
1233
1234
1235 kern_return_t
1236 ubc_upl_unmap(
1237 upl_t upl)
1238 {
1239 return(vm_upl_unmap(kernel_map, upl));
1240 }
1241
1242 kern_return_t
1243 ubc_upl_commit(
1244 upl_t upl)
1245 {
1246 upl_page_info_t *pl;
1247 kern_return_t kr;
1248
1249 pl = UPL_GET_INTERNAL_PAGE_LIST(upl);
1250 kr = upl_commit(upl, pl, MAX_UPL_TRANSFER);
1251 upl_deallocate(upl);
1252 return kr;
1253 }
1254
1255
1256 kern_return_t
1257 ubc_upl_commit_range(
1258 upl_t upl,
1259 vm_offset_t offset,
1260 vm_size_t size,
1261 int flags)
1262 {
1263 upl_page_info_t *pl;
1264 boolean_t empty;
1265 kern_return_t kr;
1266
1267 if (flags & UPL_COMMIT_FREE_ON_EMPTY)
1268 flags |= UPL_COMMIT_NOTIFY_EMPTY;
1269
1270 pl = UPL_GET_INTERNAL_PAGE_LIST(upl);
1271
1272 kr = upl_commit_range(upl, offset, size, flags,
1273 pl, MAX_UPL_TRANSFER, &empty);
1274
1275 if((flags & UPL_COMMIT_FREE_ON_EMPTY) && empty)
1276 upl_deallocate(upl);
1277
1278 return kr;
1279 }
1280
1281 kern_return_t
1282 ubc_upl_abort_range(
1283 upl_t upl,
1284 vm_offset_t offset,
1285 vm_size_t size,
1286 int abort_flags)
1287 {
1288 kern_return_t kr;
1289 boolean_t empty = FALSE;
1290
1291 if (abort_flags & UPL_ABORT_FREE_ON_EMPTY)
1292 abort_flags |= UPL_ABORT_NOTIFY_EMPTY;
1293
1294 kr = upl_abort_range(upl, offset, size, abort_flags, &empty);
1295
1296 if((abort_flags & UPL_ABORT_FREE_ON_EMPTY) && empty)
1297 upl_deallocate(upl);
1298
1299 return kr;
1300 }
1301
1302 kern_return_t
1303 ubc_upl_abort(
1304 upl_t upl,
1305 int abort_type)
1306 {
1307 kern_return_t kr;
1308
1309 kr = upl_abort(upl, abort_type);
1310 upl_deallocate(upl);
1311 return kr;
1312 }
1313
1314 upl_page_info_t *
1315 ubc_upl_pageinfo(
1316 upl_t upl)
1317 {
1318 return (UPL_GET_INTERNAL_PAGE_LIST(upl));
1319 }