2 * Copyright (c) 2000-2010 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
28 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
30 * Copyright (c) 1994 Christopher G. Demetriou
31 * Copyright (c) 1982, 1986, 1989, 1993
32 * The Regents of the University of California. All rights reserved.
33 * (c) UNIX System Laboratories, Inc.
34 * All or some portions of this file are derived from material licensed
35 * to the University of California by American Telephone and Telegraph
36 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
37 * the permission of UNIX System Laboratories, Inc.
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions
42 * 1. Redistributions of source code must retain the above copyright
43 * notice, this list of conditions and the following disclaimer.
44 * 2. Redistributions in binary form must reproduce the above copyright
45 * notice, this list of conditions and the following disclaimer in the
46 * documentation and/or other materials provided with the distribution.
47 * 3. All advertising materials mentioning features or use of this software
48 * must display the following acknowledgement:
49 * This product includes software developed by the University of
50 * California, Berkeley and its contributors.
51 * 4. Neither the name of the University nor the names of its contributors
52 * may be used to endorse or promote products derived from this software
53 * without specific prior written permission.
55 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
56 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
57 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
58 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
59 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
60 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
61 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
62 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
63 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
64 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
67 * @(#)vfs_bio.c 8.6 (Berkeley) 1/11/94
72 * Bach: The Design of the UNIX Operating System (Prentice Hall, 1986)
73 * Leffler, et al.: The Design and Implementation of the 4.3BSD
74 * UNIX Operating System (Addison Welley, 1989)
77 #include <sys/param.h>
78 #include <sys/systm.h>
79 #include <sys/proc_internal.h>
80 #include <sys/buf_internal.h>
81 #include <sys/vnode_internal.h>
82 #include <sys/mount_internal.h>
83 #include <sys/trace.h>
84 #include <sys/malloc.h>
85 #include <sys/resourcevar.h>
86 #include <miscfs/specfs/specdev.h>
88 #include <sys/kauth.h>
90 #include <kern/assert.h>
91 #endif /* DIAGNOSTIC */
92 #include <kern/task.h>
93 #include <kern/zalloc.h>
94 #include <kern/lock.h>
96 #include <sys/fslog.h> /* fslog_io_error() */
98 #include <mach/mach_types.h>
99 #include <mach/memory_object_types.h>
100 #include <kern/sched_prim.h> /* thread_block() */
102 #include <vm/vm_kern.h>
103 #include <vm/vm_pageout.h>
105 #include <sys/kdebug.h>
107 #include <libkern/OSAtomic.h>
108 #include <libkern/OSDebug.h>
109 #include <sys/ubc_internal.h>
115 static __inline__
void bufqinc(int q
);
116 static __inline__
void bufqdec(int q
);
119 int bcleanbuf(buf_t bp
, boolean_t discard
);
120 static int brecover_data(buf_t bp
);
121 static boolean_t
incore(vnode_t vp
, daddr64_t blkno
);
122 /* timeout is in msecs */
123 static buf_t
getnewbuf(int slpflag
, int slptimeo
, int *queue
);
124 static void bremfree_locked(buf_t bp
);
125 static void buf_reassign(buf_t bp
, vnode_t newvp
);
126 static errno_t
buf_acquire_locked(buf_t bp
, int flags
, int slpflag
, int slptimeo
);
127 static int buf_iterprepare(vnode_t vp
, struct buflists
*, int flags
);
128 static void buf_itercomplete(vnode_t vp
, struct buflists
*, int flags
);
129 static boolean_t
buffer_cache_gc(int);
130 static buf_t
buf_brelse_shadow(buf_t bp
);
131 static void buf_free_meta_store(buf_t bp
);
133 static buf_t
buf_create_shadow_internal(buf_t bp
, boolean_t force_copy
,
134 uintptr_t external_storage
, void (*iodone
)(buf_t
, void *), void *arg
, int priv
);
137 __private_extern__
int bdwrite_internal(buf_t
, int);
139 /* zone allocated buffer headers */
140 static void bufzoneinit(void) __attribute__((section("__TEXT, initcode")));
141 static void bcleanbuf_thread_init(void) __attribute__((section("__TEXT, initcode")));
142 static void bcleanbuf_thread(void);
144 static zone_t buf_hdr_zone
;
145 static int buf_hdr_count
;
149 * Definitions for the buffer hash lists.
151 #define BUFHASH(dvp, lbn) \
152 (&bufhashtbl[((long)(dvp) / sizeof(*(dvp)) + (int)(lbn)) & bufhash])
153 LIST_HEAD(bufhashhdr
, buf
) *bufhashtbl
, invalhash
;
156 static buf_t
incore_locked(vnode_t vp
, daddr64_t blkno
, struct bufhashhdr
*dp
);
158 /* Definitions for the buffer stats. */
159 struct bufstats bufstats
;
161 /* Number of delayed write buffers */
164 static int boot_nbuf_headers
= 0;
166 static TAILQ_HEAD(delayqueue
, buf
) delaybufqueue
;
168 static TAILQ_HEAD(ioqueue
, buf
) iobufqueue
;
169 static TAILQ_HEAD(bqueues
, buf
) bufqueues
[BQUEUES
];
170 static int needbuffer
;
171 static int need_iobuffer
;
173 static lck_grp_t
*buf_mtx_grp
;
174 static lck_attr_t
*buf_mtx_attr
;
175 static lck_grp_attr_t
*buf_mtx_grp_attr
;
176 static lck_mtx_t
*iobuffer_mtxp
;
177 static lck_mtx_t
*buf_mtxp
;
179 static int buf_busycount
;
181 static __inline__
int
190 * Insq/Remq for the buffer free lists.
193 #define binsheadfree(bp, dp, whichq) do { \
194 TAILQ_INSERT_HEAD(dp, bp, b_freelist); \
198 #define binstailfree(bp, dp, whichq) do { \
199 TAILQ_INSERT_TAIL(dp, bp, b_freelist); \
203 #define binsheadfree(bp, dp, whichq) do { \
204 TAILQ_INSERT_HEAD(dp, bp, b_freelist); \
207 #define binstailfree(bp, dp, whichq) do { \
208 TAILQ_INSERT_TAIL(dp, bp, b_freelist); \
213 #define BHASHENTCHECK(bp) \
214 if ((bp)->b_hash.le_prev != (struct buf **)0xdeadbeef) \
215 panic("%p: b_hash.le_prev is not deadbeef", (bp));
217 #define BLISTNONE(bp) \
218 (bp)->b_hash.le_next = (struct buf *)0; \
219 (bp)->b_hash.le_prev = (struct buf **)0xdeadbeef;
222 * Insq/Remq for the vnode usage lists.
224 #define bufinsvn(bp, dp) LIST_INSERT_HEAD(dp, bp, b_vnbufs)
225 #define bufremvn(bp) { \
226 LIST_REMOVE(bp, b_vnbufs); \
227 (bp)->b_vnbufs.le_next = NOLIST; \
231 * Time in seconds before a buffer on a list is
232 * considered as a stale buffer
234 #define LRU_IS_STALE 120 /* default value for the LRU */
235 #define AGE_IS_STALE 60 /* default value for the AGE */
236 #define META_IS_STALE 180 /* default value for the BQ_META */
238 int lru_is_stale
= LRU_IS_STALE
;
239 int age_is_stale
= AGE_IS_STALE
;
240 int meta_is_stale
= META_IS_STALE
;
242 #define MAXLAUNDRY 10
244 /* LIST_INSERT_HEAD() with assertions */
245 static __inline__
void
246 blistenterhead(struct bufhashhdr
* head
, buf_t bp
)
248 if ((bp
->b_hash
.le_next
= (head
)->lh_first
) != NULL
)
249 (head
)->lh_first
->b_hash
.le_prev
= &(bp
)->b_hash
.le_next
;
250 (head
)->lh_first
= bp
;
251 bp
->b_hash
.le_prev
= &(head
)->lh_first
;
252 if (bp
->b_hash
.le_prev
== (struct buf
**)0xdeadbeef)
253 panic("blistenterhead: le_prev is deadbeef");
256 static __inline__
void
257 binshash(buf_t bp
, struct bufhashhdr
*dp
)
261 #endif /* DIAGNOSTIC */
267 for(; nbp
!= NULL
; nbp
= nbp
->b_hash
.le_next
) {
269 panic("buf already in hashlist");
271 #endif /* DIAGNOSTIC */
273 blistenterhead(dp
, bp
);
276 static __inline__
void
279 if (bp
->b_hash
.le_prev
== (struct buf
**)0xdeadbeef)
280 panic("bremhash le_prev is deadbeef");
281 if (bp
->b_hash
.le_next
== bp
)
282 panic("bremhash: next points to self");
284 if (bp
->b_hash
.le_next
!= NULL
)
285 bp
->b_hash
.le_next
->b_hash
.le_prev
= bp
->b_hash
.le_prev
;
286 *bp
->b_hash
.le_prev
= (bp
)->b_hash
.le_next
;
292 static __inline__
void
293 bmovelaundry(buf_t bp
)
295 bp
->b_whichq
= BQ_LAUNDRY
;
296 bp
->b_timestamp
= buf_timestamp();
297 binstailfree(bp
, &bufqueues
[BQ_LAUNDRY
], BQ_LAUNDRY
);
301 static __inline__
void
302 buf_release_credentials(buf_t bp
)
304 if (IS_VALID_CRED(bp
->b_rcred
)) {
305 kauth_cred_unref(&bp
->b_rcred
);
307 if (IS_VALID_CRED(bp
->b_wcred
)) {
308 kauth_cred_unref(&bp
->b_wcred
);
314 buf_valid(buf_t bp
) {
316 if ( (bp
->b_flags
& (B_DONE
| B_DELWRI
)) )
322 buf_fromcache(buf_t bp
) {
324 if ( (bp
->b_flags
& B_CACHE
) )
330 buf_markinvalid(buf_t bp
) {
332 SET(bp
->b_flags
, B_INVAL
);
336 buf_markdelayed(buf_t bp
) {
338 if (!ISSET(bp
->b_flags
, B_DELWRI
)) {
339 SET(bp
->b_flags
, B_DELWRI
);
341 OSAddAtomicLong(1, &nbdwrite
);
342 buf_reassign(bp
, bp
->b_vp
);
344 SET(bp
->b_flags
, B_DONE
);
348 buf_markclean(buf_t bp
) {
350 if (ISSET(bp
->b_flags
, B_DELWRI
)) {
351 CLR(bp
->b_flags
, B_DELWRI
);
353 OSAddAtomicLong(-1, &nbdwrite
);
354 buf_reassign(bp
, bp
->b_vp
);
359 buf_markeintr(buf_t bp
) {
361 SET(bp
->b_flags
, B_EINTR
);
366 buf_markaged(buf_t bp
) {
368 SET(bp
->b_flags
, B_AGE
);
374 if ((bp
->b_flags
& B_FUA
) == B_FUA
)
380 buf_markfua(buf_t bp
) {
382 SET(bp
->b_flags
, B_FUA
);
385 #ifdef CONFIG_PROTECT
387 buf_getcpaddr(buf_t bp
) {
388 return bp
->b_cpentry
;
392 buf_setcpaddr(buf_t bp
, void *cp_entry_addr
) {
393 bp
->b_cpentry
= (struct cprotect
*) cp_entry_addr
;
398 buf_getcpaddr(buf_t bp __unused
) {
403 buf_setcpaddr(buf_t bp __unused
, void *cp_entry_addr __unused
) {
406 #endif /* CONFIG_PROTECT */
409 bufattr_throttled(bufattr_t bap
) {
410 if ( (bap
->ba_flags
& BA_THROTTLED_IO
) )
421 buf_error(buf_t bp
) {
423 return (bp
->b_error
);
427 buf_seterror(buf_t bp
, errno_t error
) {
429 if ((bp
->b_error
= error
))
430 SET(bp
->b_flags
, B_ERROR
);
432 CLR(bp
->b_flags
, B_ERROR
);
436 buf_setflags(buf_t bp
, int32_t flags
) {
438 SET(bp
->b_flags
, (flags
& BUF_X_WRFLAGS
));
442 buf_clearflags(buf_t bp
, int32_t flags
) {
444 CLR(bp
->b_flags
, (flags
& BUF_X_WRFLAGS
));
448 buf_flags(buf_t bp
) {
450 return ((bp
->b_flags
& BUF_X_RDFLAGS
));
454 buf_reset(buf_t bp
, int32_t io_flags
) {
456 CLR(bp
->b_flags
, (B_READ
| B_WRITE
| B_ERROR
| B_DONE
| B_INVAL
| B_ASYNC
| B_NOCACHE
| B_FUA
));
457 SET(bp
->b_flags
, (io_flags
& (B_ASYNC
| B_READ
| B_WRITE
| B_NOCACHE
)));
463 buf_count(buf_t bp
) {
465 return (bp
->b_bcount
);
469 buf_setcount(buf_t bp
, uint32_t bcount
) {
471 bp
->b_bcount
= bcount
;
477 return (bp
->b_bufsize
);
481 buf_setsize(buf_t bp
, uint32_t bufsize
) {
483 bp
->b_bufsize
= bufsize
;
487 buf_resid(buf_t bp
) {
489 return (bp
->b_resid
);
493 buf_setresid(buf_t bp
, uint32_t resid
) {
499 buf_dirtyoff(buf_t bp
) {
501 return (bp
->b_dirtyoff
);
505 buf_dirtyend(buf_t bp
) {
507 return (bp
->b_dirtyend
);
511 buf_setdirtyoff(buf_t bp
, uint32_t dirtyoff
) {
513 bp
->b_dirtyoff
= dirtyoff
;
517 buf_setdirtyend(buf_t bp
, uint32_t dirtyend
) {
519 bp
->b_dirtyend
= dirtyend
;
523 buf_dataptr(buf_t bp
) {
525 return (bp
->b_datap
);
529 buf_setdataptr(buf_t bp
, uintptr_t data
) {
535 buf_vnode(buf_t bp
) {
541 buf_setvnode(buf_t bp
, vnode_t vp
) {
548 buf_callback(buf_t bp
)
550 if ( !(bp
->b_flags
& B_CALL
) )
551 return ((void *) NULL
);
553 return ((void *)bp
->b_iodone
);
558 buf_setcallback(buf_t bp
, void (*callback
)(buf_t
, void *), void *transaction
)
561 bp
->b_flags
|= (B_CALL
| B_ASYNC
);
563 bp
->b_flags
&= ~B_CALL
;
564 bp
->b_transaction
= transaction
;
565 bp
->b_iodone
= callback
;
571 buf_setupl(buf_t bp
, upl_t upl
, uint32_t offset
)
574 if ( !(bp
->b_lflags
& BL_IOBUF
) )
578 bp
->b_flags
|= B_CLUSTER
;
580 bp
->b_flags
&= ~B_CLUSTER
;
582 bp
->b_uploffset
= offset
;
588 buf_clone(buf_t bp
, int io_offset
, int io_size
, void (*iodone
)(buf_t
, void *), void *arg
)
592 if (io_offset
< 0 || io_size
< 0)
595 if ((unsigned)(io_offset
+ io_size
) > (unsigned)bp
->b_bcount
)
598 if (bp
->b_flags
& B_CLUSTER
) {
599 if (io_offset
&& ((bp
->b_uploffset
+ io_offset
) & PAGE_MASK
))
602 if (((bp
->b_uploffset
+ io_offset
+ io_size
) & PAGE_MASK
) && ((io_offset
+ io_size
) < bp
->b_bcount
))
605 io_bp
= alloc_io_buf(bp
->b_vp
, 0);
607 io_bp
->b_flags
= bp
->b_flags
& (B_COMMIT_UPL
| B_META
| B_PAGEIO
| B_CLUSTER
| B_PHYS
| B_RAW
| B_ASYNC
| B_READ
| B_FUA
);
610 io_bp
->b_transaction
= arg
;
611 io_bp
->b_iodone
= iodone
;
612 io_bp
->b_flags
|= B_CALL
;
614 if (bp
->b_flags
& B_CLUSTER
) {
615 io_bp
->b_upl
= bp
->b_upl
;
616 io_bp
->b_uploffset
= bp
->b_uploffset
+ io_offset
;
618 io_bp
->b_datap
= (uintptr_t)(((char *)bp
->b_datap
) + io_offset
);
620 io_bp
->b_bcount
= io_size
;
629 if (bp
->b_lflags
& BL_SHADOW
)
636 buf_create_shadow_priv(buf_t bp
, boolean_t force_copy
, uintptr_t external_storage
, void (*iodone
)(buf_t
, void *), void *arg
)
638 return (buf_create_shadow_internal(bp
, force_copy
, external_storage
, iodone
, arg
, 1));
642 buf_create_shadow(buf_t bp
, boolean_t force_copy
, uintptr_t external_storage
, void (*iodone
)(buf_t
, void *), void *arg
)
644 return (buf_create_shadow_internal(bp
, force_copy
, external_storage
, iodone
, arg
, 0));
649 buf_create_shadow_internal(buf_t bp
, boolean_t force_copy
, uintptr_t external_storage
, void (*iodone
)(buf_t
, void *), void *arg
, int priv
)
653 KERNEL_DEBUG(0xbbbbc000 | DBG_FUNC_START
, bp
, 0, 0, 0, 0);
655 if ( !(bp
->b_flags
& B_META
) || (bp
->b_lflags
& BL_IOBUF
)) {
657 KERNEL_DEBUG(0xbbbbc000 | DBG_FUNC_END
, bp
, 0, 0, 0, 0);
660 #ifdef BUF_MAKE_PRIVATE
661 if (bp
->b_shadow_ref
&& bp
->b_data_ref
== 0 && external_storage
== 0)
662 panic("buf_create_shadow: %p is in the private state (%d, %d)", bp
, bp
->b_shadow_ref
, bp
->b_data_ref
);
664 io_bp
= alloc_io_buf(bp
->b_vp
, priv
);
666 io_bp
->b_flags
= bp
->b_flags
& (B_META
| B_ZALLOC
| B_ASYNC
| B_READ
| B_FUA
);
667 io_bp
->b_blkno
= bp
->b_blkno
;
668 io_bp
->b_lblkno
= bp
->b_lblkno
;
671 io_bp
->b_transaction
= arg
;
672 io_bp
->b_iodone
= iodone
;
673 io_bp
->b_flags
|= B_CALL
;
675 if (force_copy
== FALSE
) {
676 io_bp
->b_bcount
= bp
->b_bcount
;
677 io_bp
->b_bufsize
= bp
->b_bufsize
;
679 if (external_storage
) {
680 io_bp
->b_datap
= external_storage
;
681 #ifdef BUF_MAKE_PRIVATE
682 io_bp
->b_data_store
= NULL
;
685 io_bp
->b_datap
= bp
->b_datap
;
686 #ifdef BUF_MAKE_PRIVATE
687 io_bp
->b_data_store
= bp
;
690 *(buf_t
*)(&io_bp
->b_orig
) = bp
;
692 lck_mtx_lock_spin(buf_mtxp
);
694 io_bp
->b_lflags
|= BL_SHADOW
;
695 io_bp
->b_shadow
= bp
->b_shadow
;
696 bp
->b_shadow
= io_bp
;
699 #ifdef BUF_MAKE_PRIVATE
700 if (external_storage
)
701 io_bp
->b_lflags
|= BL_EXTERNAL
;
705 lck_mtx_unlock(buf_mtxp
);
707 if (external_storage
) {
708 #ifdef BUF_MAKE_PRIVATE
709 io_bp
->b_lflags
|= BL_EXTERNAL
;
711 io_bp
->b_bcount
= bp
->b_bcount
;
712 io_bp
->b_bufsize
= bp
->b_bufsize
;
713 io_bp
->b_datap
= external_storage
;
715 allocbuf(io_bp
, bp
->b_bcount
);
717 io_bp
->b_lflags
|= BL_IOBUF_ALLOC
;
719 bcopy((caddr_t
)bp
->b_datap
, (caddr_t
)io_bp
->b_datap
, bp
->b_bcount
);
721 #ifdef BUF_MAKE_PRIVATE
722 io_bp
->b_data_store
= NULL
;
725 KERNEL_DEBUG(0xbbbbc000 | DBG_FUNC_END
, bp
, bp
->b_shadow_ref
, 0, io_bp
, 0);
731 #ifdef BUF_MAKE_PRIVATE
733 buf_make_private(buf_t bp
)
739 KERNEL_DEBUG(0xbbbbc004 | DBG_FUNC_START
, bp
, bp
->b_shadow_ref
, 0, 0, 0);
741 if (bp
->b_shadow_ref
== 0 || bp
->b_data_ref
== 0 || ISSET(bp
->b_lflags
, BL_SHADOW
)) {
743 KERNEL_DEBUG(0xbbbbc004 | DBG_FUNC_END
, bp
, bp
->b_shadow_ref
, 0, EINVAL
, 0);
746 my_buf
.b_flags
= B_META
;
747 my_buf
.b_datap
= (uintptr_t)NULL
;
748 allocbuf(&my_buf
, bp
->b_bcount
);
750 bcopy((caddr_t
)bp
->b_datap
, (caddr_t
)my_buf
.b_datap
, bp
->b_bcount
);
752 lck_mtx_lock_spin(buf_mtxp
);
754 for (t_bp
= bp
->b_shadow
; t_bp
; t_bp
= t_bp
->b_shadow
) {
755 if ( !ISSET(bp
->b_lflags
, BL_EXTERNAL
))
760 if (ds_bp
== NULL
&& bp
->b_data_ref
)
761 panic("buf_make_private: b_data_ref != 0 && ds_bp == NULL");
763 if (ds_bp
&& (bp
->b_data_ref
== 0 || bp
->b_shadow_ref
== 0))
764 panic("buf_make_private: ref_count == 0 && ds_bp != NULL");
767 lck_mtx_unlock(buf_mtxp
);
769 buf_free_meta_store(&my_buf
);
771 KERNEL_DEBUG(0xbbbbc004 | DBG_FUNC_END
, bp
, bp
->b_shadow_ref
, 0, EINVAL
, 0);
774 for (t_bp
= bp
->b_shadow
; t_bp
; t_bp
= t_bp
->b_shadow
) {
775 if ( !ISSET(t_bp
->b_lflags
, BL_EXTERNAL
))
776 t_bp
->b_data_store
= ds_bp
;
778 ds_bp
->b_data_ref
= bp
->b_data_ref
;
781 bp
->b_datap
= my_buf
.b_datap
;
783 lck_mtx_unlock(buf_mtxp
);
785 KERNEL_DEBUG(0xbbbbc004 | DBG_FUNC_END
, bp
, bp
->b_shadow_ref
, 0, 0, 0);
792 buf_setfilter(buf_t bp
, void (*filter
)(buf_t
, void *), void *transaction
,
793 void (**old_iodone
)(buf_t
, void *), void **old_transaction
)
796 *old_iodone
= bp
->b_iodone
;
798 *old_transaction
= bp
->b_transaction
;
800 bp
->b_transaction
= transaction
;
801 bp
->b_iodone
= filter
;
803 bp
->b_flags
|= B_FILTER
;
805 bp
->b_flags
&= ~B_FILTER
;
810 buf_blkno(buf_t bp
) {
812 return (bp
->b_blkno
);
816 buf_lblkno(buf_t bp
) {
818 return (bp
->b_lblkno
);
822 buf_setblkno(buf_t bp
, daddr64_t blkno
) {
828 buf_setlblkno(buf_t bp
, daddr64_t lblkno
) {
830 bp
->b_lblkno
= lblkno
;
834 buf_device(buf_t bp
) {
840 buf_setdevice(buf_t bp
, vnode_t vp
) {
842 if ((vp
->v_type
!= VBLK
) && (vp
->v_type
!= VCHR
))
844 bp
->b_dev
= vp
->v_rdev
;
851 buf_drvdata(buf_t bp
) {
853 return (bp
->b_drvdata
);
857 buf_setdrvdata(buf_t bp
, void *drvdata
) {
859 bp
->b_drvdata
= drvdata
;
863 buf_fsprivate(buf_t bp
) {
865 return (bp
->b_fsprivate
);
869 buf_setfsprivate(buf_t bp
, void *fsprivate
) {
871 bp
->b_fsprivate
= fsprivate
;
875 buf_rcred(buf_t bp
) {
877 return (bp
->b_rcred
);
881 buf_wcred(buf_t bp
) {
883 return (bp
->b_wcred
);
893 buf_uploffset(buf_t bp
) {
895 return ((uint32_t)(bp
->b_uploffset
));
906 buf_map(buf_t bp
, caddr_t
*io_addr
)
912 if ( !(bp
->b_flags
& B_CLUSTER
)) {
913 *io_addr
= (caddr_t
)bp
->b_datap
;
916 real_bp
= (buf_t
)(bp
->b_real_bp
);
918 if (real_bp
&& real_bp
->b_datap
) {
920 * b_real_bp is only valid if B_CLUSTER is SET
921 * if it's non-zero, than someone did a cluster_bp call
922 * if the backing physical pages were already mapped
923 * in before the call to cluster_bp (non-zero b_datap),
924 * than we just use that mapping
926 *io_addr
= (caddr_t
)real_bp
->b_datap
;
929 kret
= ubc_upl_map(bp
->b_upl
, &vaddr
); /* Map it in */
931 if (kret
!= KERN_SUCCESS
) {
936 vaddr
+= bp
->b_uploffset
;
938 *io_addr
= (caddr_t
)vaddr
;
949 if ( !(bp
->b_flags
& B_CLUSTER
))
952 * see buf_map for the explanation
954 real_bp
= (buf_t
)(bp
->b_real_bp
);
956 if (real_bp
&& real_bp
->b_datap
)
959 if ((bp
->b_lflags
& BL_IOBUF
) &&
960 ((bp
->b_flags
& (B_PAGEIO
| B_READ
)) != (B_PAGEIO
| B_READ
))) {
962 * ignore pageins... the 'right' thing will
963 * happen due to the way we handle speculative
966 * when we commit these pages, we'll hit
967 * it with UPL_COMMIT_INACTIVE which
968 * will clear the reference bit that got
969 * turned on when we touched the mapping
971 bp
->b_flags
|= B_AGE
;
973 kret
= ubc_upl_unmap(bp
->b_upl
);
975 if (kret
!= KERN_SUCCESS
)
982 buf_clear(buf_t bp
) {
985 if (buf_map(bp
, &baddr
) == 0) {
986 bzero(baddr
, bp
->b_bcount
);
993 * Read or write a buffer that is not contiguous on disk.
994 * buffer is marked done/error at the conclusion
997 buf_strategy_fragmented(vnode_t devvp
, buf_t bp
, off_t f_offset
, size_t contig_bytes
)
999 vnode_t vp
= buf_vnode(bp
);
1000 buf_t io_bp
; /* For reading or writing a single block */
1003 size_t io_contig_bytes
;
1009 * save our starting point... the bp was already mapped
1010 * in buf_strategy before we got called
1011 * no sense doing it again.
1013 io_blkno
= bp
->b_blkno
;
1015 * Make sure we redo this mapping for the next I/O
1016 * i.e. this can never be a 'permanent' mapping
1018 bp
->b_blkno
= bp
->b_lblkno
;
1021 * Get an io buffer to do the deblocking
1023 io_bp
= alloc_io_buf(devvp
, 0);
1025 io_bp
->b_lblkno
= bp
->b_lblkno
;
1026 io_bp
->b_datap
= bp
->b_datap
;
1027 io_resid
= bp
->b_bcount
;
1028 io_direction
= bp
->b_flags
& B_READ
;
1029 io_contig_bytes
= contig_bytes
;
1031 if (bp
->b_flags
& B_READ
)
1032 bmap_flags
= VNODE_READ
;
1034 bmap_flags
= VNODE_WRITE
;
1039 * this is unexepected, but we'll allow for it
1041 bzero((caddr_t
)io_bp
->b_datap
, (int)io_contig_bytes
);
1043 io_bp
->b_bcount
= io_contig_bytes
;
1044 io_bp
->b_bufsize
= io_contig_bytes
;
1045 io_bp
->b_resid
= io_contig_bytes
;
1046 io_bp
->b_blkno
= io_blkno
;
1048 buf_reset(io_bp
, io_direction
);
1051 * Call the device to do the I/O and wait for it. Make sure the appropriate party is charged for write
1054 if (!ISSET(bp
->b_flags
, B_READ
))
1055 OSAddAtomic(1, &devvp
->v_numoutput
);
1057 if ((error
= VNOP_STRATEGY(io_bp
)))
1059 if ((error
= (int)buf_biowait(io_bp
)))
1061 if (io_bp
->b_resid
) {
1062 io_resid
-= (io_contig_bytes
- io_bp
->b_resid
);
1066 if ((io_resid
-= io_contig_bytes
) == 0)
1068 f_offset
+= io_contig_bytes
;
1069 io_bp
->b_datap
+= io_contig_bytes
;
1072 * Map the current position to a physical block number
1074 if ((error
= VNOP_BLOCKMAP(vp
, f_offset
, io_resid
, &io_blkno
, &io_contig_bytes
, NULL
, bmap_flags
, NULL
)))
1080 buf_seterror(bp
, error
);
1081 bp
->b_resid
= io_resid
;
1083 * This I/O is now complete
1092 * struct vnop_strategy_args {
1097 buf_strategy(vnode_t devvp
, void *ap
)
1099 buf_t bp
= ((struct vnop_strategy_args
*)ap
)->a_bp
;
1100 vnode_t vp
= bp
->b_vp
;
1104 int dtrace_io_start_flag
= 0; /* We only want to trip the io:::start
1105 * probe once, with the true phisical
1106 * block in place (b_blkno)
1111 if (vp
== NULL
|| vp
->v_type
== VCHR
|| vp
->v_type
== VBLK
)
1112 panic("buf_strategy: b_vp == NULL || vtype == VCHR | VBLK\n");
1114 * associate the physical device with
1115 * with this buf_t even if we don't
1116 * end up issuing the I/O...
1118 bp
->b_dev
= devvp
->v_rdev
;
1120 if (bp
->b_flags
& B_READ
)
1121 bmap_flags
= VNODE_READ
;
1123 bmap_flags
= VNODE_WRITE
;
1125 if ( !(bp
->b_flags
& B_CLUSTER
)) {
1127 if ( (bp
->b_upl
) ) {
1129 * we have a UPL associated with this bp
1130 * go through cluster_bp which knows how
1131 * to deal with filesystem block sizes
1132 * that aren't equal to the page size
1134 DTRACE_IO1(start
, buf_t
, bp
);
1135 return (cluster_bp(bp
));
1137 if (bp
->b_blkno
== bp
->b_lblkno
) {
1139 size_t contig_bytes
;
1141 if ((error
= VNOP_BLKTOOFF(vp
, bp
->b_lblkno
, &f_offset
))) {
1142 DTRACE_IO1(start
, buf_t
, bp
);
1143 buf_seterror(bp
, error
);
1148 if ((error
= VNOP_BLOCKMAP(vp
, f_offset
, bp
->b_bcount
, &bp
->b_blkno
, &contig_bytes
, NULL
, bmap_flags
, NULL
))) {
1149 DTRACE_IO1(start
, buf_t
, bp
);
1150 buf_seterror(bp
, error
);
1156 DTRACE_IO1(start
, buf_t
, bp
);
1158 dtrace_io_start_flag
= 1;
1159 #endif /* CONFIG_DTRACE */
1161 if ((bp
->b_blkno
== -1) || (contig_bytes
== 0)) {
1162 /* Set block number to force biodone later */
1166 else if ((long)contig_bytes
< bp
->b_bcount
) {
1167 return (buf_strategy_fragmented(devvp
, bp
, f_offset
, contig_bytes
));
1172 if (dtrace_io_start_flag
== 0) {
1173 DTRACE_IO1(start
, buf_t
, bp
);
1174 dtrace_io_start_flag
= 1;
1176 #endif /* CONFIG_DTRACE */
1178 if (bp
->b_blkno
== -1) {
1185 if (dtrace_io_start_flag
== 0)
1186 DTRACE_IO1(start
, buf_t
, bp
);
1187 #endif /* CONFIG_DTRACE */
1190 * we can issue the I/O because...
1191 * either B_CLUSTER is set which
1192 * means that the I/O is properly set
1193 * up to be a multiple of the page size, or
1194 * we were able to successfully set up the
1195 * phsyical block mapping
1197 return (VOCALL(devvp
->v_op
, VOFFSET(vnop_strategy
), ap
));
1203 buf_alloc(vnode_t vp
)
1205 return(alloc_io_buf(vp
, 0));
1209 buf_free(buf_t bp
) {
1216 * iterate buffers for the specified vp.
1217 * if BUF_SCAN_DIRTY is set, do the dirty list
1218 * if BUF_SCAN_CLEAN is set, do the clean list
1219 * if neither flag is set, default to BUF_SCAN_DIRTY
1220 * if BUF_NOTIFY_BUSY is set, call the callout function using a NULL bp for busy pages
1223 struct buf_iterate_info_t
{
1225 struct buflists
*listhead
;
1229 buf_iterate(vnode_t vp
, int (*callout
)(buf_t
, void *), int flags
, void *arg
)
1233 struct buflists local_iterblkhd
;
1234 int lock_flags
= BAC_NOWAIT
| BAC_REMOVE
;
1235 int notify_busy
= flags
& BUF_NOTIFY_BUSY
;
1236 struct buf_iterate_info_t list
[2];
1239 if (flags
& BUF_SKIP_LOCKED
)
1240 lock_flags
|= BAC_SKIP_LOCKED
;
1241 if (flags
& BUF_SKIP_NONLOCKED
)
1242 lock_flags
|= BAC_SKIP_NONLOCKED
;
1244 if ( !(flags
& (BUF_SCAN_DIRTY
| BUF_SCAN_CLEAN
)))
1245 flags
|= BUF_SCAN_DIRTY
;
1249 if (flags
& BUF_SCAN_DIRTY
) {
1250 list
[num_lists
].flag
= VBI_DIRTY
;
1251 list
[num_lists
].listhead
= &vp
->v_dirtyblkhd
;
1254 if (flags
& BUF_SCAN_CLEAN
) {
1255 list
[num_lists
].flag
= VBI_CLEAN
;
1256 list
[num_lists
].listhead
= &vp
->v_cleanblkhd
;
1260 for (i
= 0; i
< num_lists
; i
++) {
1261 lck_mtx_lock(buf_mtxp
);
1263 if (buf_iterprepare(vp
, &local_iterblkhd
, list
[i
].flag
)) {
1264 lck_mtx_unlock(buf_mtxp
);
1267 while (!LIST_EMPTY(&local_iterblkhd
)) {
1268 bp
= LIST_FIRST(&local_iterblkhd
);
1269 LIST_REMOVE(bp
, b_vnbufs
);
1270 LIST_INSERT_HEAD(list
[i
].listhead
, bp
, b_vnbufs
);
1272 if (buf_acquire_locked(bp
, lock_flags
, 0, 0)) {
1280 lck_mtx_unlock(buf_mtxp
);
1282 retval
= callout(bp
, arg
);
1291 case BUF_RETURNED_DONE
:
1294 lck_mtx_lock(buf_mtxp
);
1296 case BUF_CLAIMED_DONE
:
1297 lck_mtx_lock(buf_mtxp
);
1300 lck_mtx_lock(buf_mtxp
);
1301 } /* while list has more nodes */
1303 buf_itercomplete(vp
, &local_iterblkhd
, list
[i
].flag
);
1304 lck_mtx_unlock(buf_mtxp
);
1305 } /* for each list */
1310 * Flush out and invalidate all buffers associated with a vnode.
1313 buf_invalidateblks(vnode_t vp
, int flags
, int slpflag
, int slptimeo
)
1318 int must_rescan
= 1;
1319 struct buflists local_iterblkhd
;
1322 if (LIST_EMPTY(&vp
->v_cleanblkhd
) && LIST_EMPTY(&vp
->v_dirtyblkhd
))
1325 lck_mtx_lock(buf_mtxp
);
1328 if (must_rescan
== 0)
1330 * the lists may not be empty, but all that's left at this
1331 * point are metadata or B_LOCKED buffers which are being
1332 * skipped... we know this because we made it through both
1333 * the clean and dirty lists without dropping buf_mtxp...
1334 * each time we drop buf_mtxp we bump "must_rescan"
1337 if (LIST_EMPTY(&vp
->v_cleanblkhd
) && LIST_EMPTY(&vp
->v_dirtyblkhd
))
1341 * iterate the clean list
1343 if (buf_iterprepare(vp
, &local_iterblkhd
, VBI_CLEAN
)) {
1344 goto try_dirty_list
;
1346 while (!LIST_EMPTY(&local_iterblkhd
)) {
1348 bp
= LIST_FIRST(&local_iterblkhd
);
1350 LIST_REMOVE(bp
, b_vnbufs
);
1351 LIST_INSERT_HEAD(&vp
->v_cleanblkhd
, bp
, b_vnbufs
);
1354 * some filesystems distinguish meta data blocks with a negative logical block #
1356 if ((flags
& BUF_SKIP_META
) && (bp
->b_lblkno
< 0 || ISSET(bp
->b_flags
, B_META
)))
1359 aflags
= BAC_REMOVE
;
1361 if ( !(flags
& BUF_INVALIDATE_LOCKED
) )
1362 aflags
|= BAC_SKIP_LOCKED
;
1364 if ( (error
= (int)buf_acquire_locked(bp
, aflags
, slpflag
, slptimeo
)) ) {
1365 if (error
== EDEADLK
)
1367 * this buffer was marked B_LOCKED...
1368 * we didn't drop buf_mtxp, so we
1369 * we don't need to rescan
1372 if (error
== EAGAIN
) {
1374 * found a busy buffer... we blocked and
1375 * dropped buf_mtxp, so we're going to
1376 * need to rescan after this pass is completed
1382 * got some kind of 'real' error out of the msleep
1383 * in buf_acquire_locked, terminate the scan and return the error
1385 buf_itercomplete(vp
, &local_iterblkhd
, VBI_CLEAN
);
1387 lck_mtx_unlock(buf_mtxp
);
1390 lck_mtx_unlock(buf_mtxp
);
1392 if (bp
->b_flags
& B_LOCKED
)
1393 KERNEL_DEBUG(0xbbbbc038, bp
, 0, 0, 0, 0);
1395 CLR(bp
->b_flags
, B_LOCKED
);
1396 SET(bp
->b_flags
, B_INVAL
);
1399 lck_mtx_lock(buf_mtxp
);
1402 * by dropping buf_mtxp, we allow new
1403 * buffers to be added to the vnode list(s)
1404 * we'll have to rescan at least once more
1405 * if the queues aren't empty
1409 buf_itercomplete(vp
, &local_iterblkhd
, VBI_CLEAN
);
1413 * Now iterate on dirty blks
1415 if (buf_iterprepare(vp
, &local_iterblkhd
, VBI_DIRTY
)) {
1418 while (!LIST_EMPTY(&local_iterblkhd
)) {
1419 bp
= LIST_FIRST(&local_iterblkhd
);
1421 LIST_REMOVE(bp
, b_vnbufs
);
1422 LIST_INSERT_HEAD(&vp
->v_dirtyblkhd
, bp
, b_vnbufs
);
1425 * some filesystems distinguish meta data blocks with a negative logical block #
1427 if ((flags
& BUF_SKIP_META
) && (bp
->b_lblkno
< 0 || ISSET(bp
->b_flags
, B_META
)))
1430 aflags
= BAC_REMOVE
;
1432 if ( !(flags
& BUF_INVALIDATE_LOCKED
) )
1433 aflags
|= BAC_SKIP_LOCKED
;
1435 if ( (error
= (int)buf_acquire_locked(bp
, aflags
, slpflag
, slptimeo
)) ) {
1436 if (error
== EDEADLK
)
1438 * this buffer was marked B_LOCKED...
1439 * we didn't drop buf_mtxp, so we
1440 * we don't need to rescan
1443 if (error
== EAGAIN
) {
1445 * found a busy buffer... we blocked and
1446 * dropped buf_mtxp, so we're going to
1447 * need to rescan after this pass is completed
1453 * got some kind of 'real' error out of the msleep
1454 * in buf_acquire_locked, terminate the scan and return the error
1456 buf_itercomplete(vp
, &local_iterblkhd
, VBI_DIRTY
);
1458 lck_mtx_unlock(buf_mtxp
);
1461 lck_mtx_unlock(buf_mtxp
);
1463 if (bp
->b_flags
& B_LOCKED
)
1464 KERNEL_DEBUG(0xbbbbc038, bp
, 0, 0, 1, 0);
1466 CLR(bp
->b_flags
, B_LOCKED
);
1467 SET(bp
->b_flags
, B_INVAL
);
1469 if (ISSET(bp
->b_flags
, B_DELWRI
) && (flags
& BUF_WRITE_DATA
))
1470 (void) VNOP_BWRITE(bp
);
1474 lck_mtx_lock(buf_mtxp
);
1476 * by dropping buf_mtxp, we allow new
1477 * buffers to be added to the vnode list(s)
1478 * we'll have to rescan at least once more
1479 * if the queues aren't empty
1483 buf_itercomplete(vp
, &local_iterblkhd
, VBI_DIRTY
);
1485 lck_mtx_unlock(buf_mtxp
);
1491 buf_flushdirtyblks(vnode_t vp
, int wait
, int flags
, const char *msg
) {
1493 int writes_issued
= 0;
1496 struct buflists local_iterblkhd
;
1497 int lock_flags
= BAC_NOWAIT
| BAC_REMOVE
;
1499 if (flags
& BUF_SKIP_LOCKED
)
1500 lock_flags
|= BAC_SKIP_LOCKED
;
1501 if (flags
& BUF_SKIP_NONLOCKED
)
1502 lock_flags
|= BAC_SKIP_NONLOCKED
;
1504 lck_mtx_lock(buf_mtxp
);
1506 if (buf_iterprepare(vp
, &local_iterblkhd
, VBI_DIRTY
) == 0) {
1507 while (!LIST_EMPTY(&local_iterblkhd
)) {
1508 bp
= LIST_FIRST(&local_iterblkhd
);
1509 LIST_REMOVE(bp
, b_vnbufs
);
1510 LIST_INSERT_HEAD(&vp
->v_dirtyblkhd
, bp
, b_vnbufs
);
1512 if ((error
= buf_acquire_locked(bp
, lock_flags
, 0, 0)) == EBUSY
)
1516 lck_mtx_unlock(buf_mtxp
);
1518 bp
->b_flags
&= ~B_LOCKED
;
1521 * Wait for I/O associated with indirect blocks to complete,
1522 * since there is no way to quickly wait for them below.
1524 if ((bp
->b_vp
== vp
) || (wait
== 0))
1525 (void) buf_bawrite(bp
);
1527 (void) VNOP_BWRITE(bp
);
1530 lck_mtx_lock(buf_mtxp
);
1532 buf_itercomplete(vp
, &local_iterblkhd
, VBI_DIRTY
);
1534 lck_mtx_unlock(buf_mtxp
);
1537 (void)vnode_waitforwrites(vp
, 0, 0, 0, msg
);
1539 if (vp
->v_dirtyblkhd
.lh_first
&& busy
) {
1541 * we had one or more BUSY buffers on
1542 * the dirtyblock list... most likely
1543 * these are due to delayed writes that
1544 * were moved to the bclean queue but
1545 * have not yet been 'written'.
1546 * if we issued some writes on the
1547 * previous pass, we try again immediately
1548 * if we didn't, we'll sleep for some time
1549 * to allow the state to change...
1551 if (writes_issued
== 0) {
1552 (void)tsleep((caddr_t
)&vp
->v_numoutput
,
1553 PRIBIO
+ 1, "vnode_flushdirtyblks", hz
/20);
1565 * called with buf_mtxp held...
1566 * this lock protects the queue manipulation
1569 buf_iterprepare(vnode_t vp
, struct buflists
*iterheadp
, int flags
)
1571 struct buflists
* listheadp
;
1573 if (flags
& VBI_DIRTY
)
1574 listheadp
= &vp
->v_dirtyblkhd
;
1576 listheadp
= &vp
->v_cleanblkhd
;
1578 while (vp
->v_iterblkflags
& VBI_ITER
) {
1579 vp
->v_iterblkflags
|= VBI_ITERWANT
;
1580 msleep(&vp
->v_iterblkflags
, buf_mtxp
, 0, "buf_iterprepare", NULL
);
1582 if (LIST_EMPTY(listheadp
)) {
1583 LIST_INIT(iterheadp
);
1586 vp
->v_iterblkflags
|= VBI_ITER
;
1588 iterheadp
->lh_first
= listheadp
->lh_first
;
1589 listheadp
->lh_first
->b_vnbufs
.le_prev
= &iterheadp
->lh_first
;
1590 LIST_INIT(listheadp
);
1596 * called with buf_mtxp held...
1597 * this lock protects the queue manipulation
1600 buf_itercomplete(vnode_t vp
, struct buflists
*iterheadp
, int flags
)
1602 struct buflists
* listheadp
;
1605 if (flags
& VBI_DIRTY
)
1606 listheadp
= &vp
->v_dirtyblkhd
;
1608 listheadp
= &vp
->v_cleanblkhd
;
1610 while (!LIST_EMPTY(iterheadp
)) {
1611 bp
= LIST_FIRST(iterheadp
);
1612 LIST_REMOVE(bp
, b_vnbufs
);
1613 LIST_INSERT_HEAD(listheadp
, bp
, b_vnbufs
);
1615 vp
->v_iterblkflags
&= ~VBI_ITER
;
1617 if (vp
->v_iterblkflags
& VBI_ITERWANT
) {
1618 vp
->v_iterblkflags
&= ~VBI_ITERWANT
;
1619 wakeup(&vp
->v_iterblkflags
);
1625 bremfree_locked(buf_t bp
)
1627 struct bqueues
*dp
= NULL
;
1630 whichq
= bp
->b_whichq
;
1633 if (bp
->b_shadow_ref
== 0)
1634 panic("bremfree_locked: %p not on freelist", bp
);
1636 * there are clones pointing to 'bp'...
1637 * therefore, it was not put on a freelist
1638 * when buf_brelse was last called on 'bp'
1643 * We only calculate the head of the freelist when removing
1644 * the last element of the list as that is the only time that
1645 * it is needed (e.g. to reset the tail pointer).
1647 * NB: This makes an assumption about how tailq's are implemented.
1649 if (bp
->b_freelist
.tqe_next
== NULL
) {
1650 dp
= &bufqueues
[whichq
];
1652 if (dp
->tqh_last
!= &bp
->b_freelist
.tqe_next
)
1653 panic("bremfree: lost tail");
1655 TAILQ_REMOVE(dp
, bp
, b_freelist
);
1660 if (whichq
== BQ_LAUNDRY
)
1664 bp
->b_timestamp
= 0;
1669 * Associate a buffer with a vnode.
1670 * buf_mtxp must be locked on entry
1673 bgetvp_locked(vnode_t vp
, buf_t bp
)
1677 panic("bgetvp_locked: not free");
1679 if (vp
->v_type
== VBLK
|| vp
->v_type
== VCHR
)
1680 bp
->b_dev
= vp
->v_rdev
;
1684 * Insert onto list for new vnode.
1686 bufinsvn(bp
, &vp
->v_cleanblkhd
);
1690 * Disassociate a buffer from a vnode.
1691 * buf_mtxp must be locked on entry
1694 brelvp_locked(buf_t bp
)
1697 * Delete from old vnode list, if on one.
1699 if (bp
->b_vnbufs
.le_next
!= NOLIST
)
1702 bp
->b_vp
= (vnode_t
)NULL
;
1706 * Reassign a buffer from one vnode to another.
1707 * Used to assign file specific control information
1708 * (indirect blocks) to the vnode to which they belong.
1711 buf_reassign(buf_t bp
, vnode_t newvp
)
1713 struct buflists
*listheadp
;
1715 if (newvp
== NULL
) {
1716 printf("buf_reassign: NULL");
1719 lck_mtx_lock_spin(buf_mtxp
);
1722 * Delete from old vnode list, if on one.
1724 if (bp
->b_vnbufs
.le_next
!= NOLIST
)
1727 * If dirty, put on list of dirty buffers;
1728 * otherwise insert onto list of clean buffers.
1730 if (ISSET(bp
->b_flags
, B_DELWRI
))
1731 listheadp
= &newvp
->v_dirtyblkhd
;
1733 listheadp
= &newvp
->v_cleanblkhd
;
1734 bufinsvn(bp
, listheadp
);
1736 lck_mtx_unlock(buf_mtxp
);
1739 static __inline__
void
1740 bufhdrinit(buf_t bp
)
1742 bzero((char *)bp
, sizeof *bp
);
1744 bp
->b_rcred
= NOCRED
;
1745 bp
->b_wcred
= NOCRED
;
1746 bp
->b_vnbufs
.le_next
= NOLIST
;
1747 bp
->b_flags
= B_INVAL
;
1753 * Initialize buffers and hash links for buffers.
1755 __private_extern__
void
1763 /* Initialize the buffer queues ('freelists') and the hash table */
1764 for (dp
= bufqueues
; dp
< &bufqueues
[BQUEUES
]; dp
++)
1766 bufhashtbl
= hashinit(nbuf_hashelements
, M_CACHE
, &bufhash
);
1770 /* Initialize the buffer headers */
1771 for (i
= 0; i
< max_nbuf_headers
; i
++) {
1773 bp
= &buf_headers
[i
];
1777 dp
= &bufqueues
[BQ_EMPTY
];
1778 bp
->b_whichq
= BQ_EMPTY
;
1779 bp
->b_timestamp
= buf_timestamp();
1780 binsheadfree(bp
, dp
, BQ_EMPTY
);
1781 binshash(bp
, &invalhash
);
1783 boot_nbuf_headers
= nbuf_headers
;
1785 TAILQ_INIT(&iobufqueue
);
1786 TAILQ_INIT(&delaybufqueue
);
1788 for (; i
< nbuf_headers
+ niobuf_headers
; i
++) {
1789 bp
= &buf_headers
[i
];
1792 binsheadfree(bp
, &iobufqueue
, -1);
1796 * allocate lock group attribute and group
1798 buf_mtx_grp_attr
= lck_grp_attr_alloc_init();
1799 buf_mtx_grp
= lck_grp_alloc_init("buffer cache", buf_mtx_grp_attr
);
1802 * allocate the lock attribute
1804 buf_mtx_attr
= lck_attr_alloc_init();
1807 * allocate and initialize mutex's for the buffer and iobuffer pools
1809 buf_mtxp
= lck_mtx_alloc_init(buf_mtx_grp
, buf_mtx_attr
);
1810 iobuffer_mtxp
= lck_mtx_alloc_init(buf_mtx_grp
, buf_mtx_attr
);
1812 if (iobuffer_mtxp
== NULL
)
1813 panic("couldn't create iobuffer mutex");
1815 if (buf_mtxp
== NULL
)
1816 panic("couldn't create buf mutex");
1819 * allocate and initialize cluster specific global locks...
1823 printf("using %d buffer headers and %d cluster IO buffer headers\n",
1824 nbuf_headers
, niobuf_headers
);
1826 /* Set up zones used by the buffer cache */
1829 /* start the bcleanbuf() thread */
1830 bcleanbuf_thread_init();
1832 /* Register a callout for relieving vm pressure */
1833 if (vm_set_buffer_cleanup_callout(buffer_cache_gc
) != KERN_SUCCESS
) {
1834 panic("Couldn't register buffer cache callout for vm pressure!\n");
1839 static void bufq_balance_thread_init(void) __attribute__((section("__TEXT, initcode")));
1840 /* create a thread to do dynamic buffer queue balancing */
1841 bufq_balance_thread_init();
1849 * Zones for the meta data buffers
1853 #define MAXMETA 8192
1855 struct meta_zone_entry
{
1859 const char *mz_name
;
1862 struct meta_zone_entry meta_zones
[] = {
1863 {NULL
, (MINMETA
* 1), 128 * (MINMETA
* 1), "buf.512" },
1864 {NULL
, (MINMETA
* 2), 64 * (MINMETA
* 2), "buf.1024" },
1865 {NULL
, (MINMETA
* 4), 16 * (MINMETA
* 4), "buf.2048" },
1866 {NULL
, (MINMETA
* 8), 512 * (MINMETA
* 8), "buf.4096" },
1867 {NULL
, (MINMETA
* 16), 512 * (MINMETA
* 16), "buf.8192" },
1868 {NULL
, 0, 0, "" } /* End */
1872 * Initialize the meta data zones
1879 for (i
= 0; meta_zones
[i
].mz_size
!= 0; i
++) {
1880 meta_zones
[i
].mz_zone
=
1881 zinit(meta_zones
[i
].mz_size
,
1882 meta_zones
[i
].mz_max
,
1884 meta_zones
[i
].mz_name
);
1885 zone_change(meta_zones
[i
].mz_zone
, Z_CALLERACCT
, FALSE
);
1887 buf_hdr_zone
= zinit(sizeof(struct buf
), 32, PAGE_SIZE
, "buf headers");
1888 zone_change(buf_hdr_zone
, Z_CALLERACCT
, FALSE
);
1891 static __inline__ zone_t
1892 getbufzone(size_t size
)
1896 if ((size
% 512) || (size
< MINMETA
) || (size
> MAXMETA
))
1897 panic("getbufzone: incorect size = %lu", size
);
1899 for (i
= 0; meta_zones
[i
].mz_size
!= 0; i
++) {
1900 if (meta_zones
[i
].mz_size
>= size
)
1904 return (meta_zones
[i
].mz_zone
);
1910 bio_doread(vnode_t vp
, daddr64_t blkno
, int size
, kauth_cred_t cred
, int async
, int queuetype
)
1914 bp
= buf_getblk(vp
, blkno
, size
, 0, 0, queuetype
);
1917 * If buffer does not have data valid, start a read.
1918 * Note that if buffer is B_INVAL, buf_getblk() won't return it.
1919 * Therefore, it's valid if it's I/O has completed or been delayed.
1921 if (!ISSET(bp
->b_flags
, (B_DONE
| B_DELWRI
))) {
1926 /* Start I/O for the buffer (keeping credentials). */
1927 SET(bp
->b_flags
, B_READ
| async
);
1928 if (IS_VALID_CRED(cred
) && !IS_VALID_CRED(bp
->b_rcred
)) {
1929 kauth_cred_ref(cred
);
1935 trace(TR_BREADMISS
, pack(vp
, size
), blkno
);
1937 /* Pay for the read. */
1938 if (p
&& p
->p_stats
)
1939 OSIncrementAtomicLong(&p
->p_stats
->p_ru
.ru_inblock
); /* XXX */
1943 * since we asked for an ASYNC I/O
1944 * the biodone will do the brelse
1945 * we don't want to pass back a bp
1946 * that we don't 'own'
1955 trace(TR_BREADHIT
, pack(vp
, size
), blkno
);
1961 * Perform the reads for buf_breadn() and buf_meta_breadn().
1962 * Trivial modification to the breada algorithm presented in Bach (p.55).
1965 do_breadn_for_type(vnode_t vp
, daddr64_t blkno
, int size
, daddr64_t
*rablks
, int *rasizes
,
1966 int nrablks
, kauth_cred_t cred
, buf_t
*bpp
, int queuetype
)
1971 bp
= *bpp
= bio_doread(vp
, blkno
, size
, cred
, 0, queuetype
);
1974 * For each of the read-ahead blocks, start a read, if necessary.
1976 for (i
= 0; i
< nrablks
; i
++) {
1977 /* If it's in the cache, just go on to next one. */
1978 if (incore(vp
, rablks
[i
]))
1981 /* Get a buffer for the read-ahead block */
1982 (void) bio_doread(vp
, rablks
[i
], rasizes
[i
], cred
, B_ASYNC
, queuetype
);
1985 /* Otherwise, we had to start a read for it; wait until it's valid. */
1986 return (buf_biowait(bp
));
1991 * Read a disk block.
1992 * This algorithm described in Bach (p.54).
1995 buf_bread(vnode_t vp
, daddr64_t blkno
, int size
, kauth_cred_t cred
, buf_t
*bpp
)
1999 /* Get buffer for block. */
2000 bp
= *bpp
= bio_doread(vp
, blkno
, size
, cred
, 0, BLK_READ
);
2002 /* Wait for the read to complete, and return result. */
2003 return (buf_biowait(bp
));
2007 * Read a disk block. [bread() for meta-data]
2008 * This algorithm described in Bach (p.54).
2011 buf_meta_bread(vnode_t vp
, daddr64_t blkno
, int size
, kauth_cred_t cred
, buf_t
*bpp
)
2015 /* Get buffer for block. */
2016 bp
= *bpp
= bio_doread(vp
, blkno
, size
, cred
, 0, BLK_META
);
2018 /* Wait for the read to complete, and return result. */
2019 return (buf_biowait(bp
));
2023 * Read-ahead multiple disk blocks. The first is sync, the rest async.
2026 buf_breadn(vnode_t vp
, daddr64_t blkno
, int size
, daddr64_t
*rablks
, int *rasizes
, int nrablks
, kauth_cred_t cred
, buf_t
*bpp
)
2028 return (do_breadn_for_type(vp
, blkno
, size
, rablks
, rasizes
, nrablks
, cred
, bpp
, BLK_READ
));
2032 * Read-ahead multiple disk blocks. The first is sync, the rest async.
2033 * [buf_breadn() for meta-data]
2036 buf_meta_breadn(vnode_t vp
, daddr64_t blkno
, int size
, daddr64_t
*rablks
, int *rasizes
, int nrablks
, kauth_cred_t cred
, buf_t
*bpp
)
2038 return (do_breadn_for_type(vp
, blkno
, size
, rablks
, rasizes
, nrablks
, cred
, bpp
, BLK_META
));
2042 * Block write. Described in Bach (p.56)
2045 buf_bwrite(buf_t bp
)
2047 int sync
, wasdelayed
;
2049 proc_t p
= current_proc();
2050 vnode_t vp
= bp
->b_vp
;
2052 if (bp
->b_datap
== 0) {
2053 if (brecover_data(bp
) == 0)
2056 /* Remember buffer type, to switch on it later. */
2057 sync
= !ISSET(bp
->b_flags
, B_ASYNC
);
2058 wasdelayed
= ISSET(bp
->b_flags
, B_DELWRI
);
2059 CLR(bp
->b_flags
, (B_READ
| B_DONE
| B_ERROR
| B_DELWRI
));
2062 OSAddAtomicLong(-1, &nbdwrite
);
2066 * If not synchronous, pay for the I/O operation and make
2067 * sure the buf is on the correct vnode queue. We have
2068 * to do this now, because if we don't, the vnode may not
2069 * be properly notified that its I/O has completed.
2072 buf_reassign(bp
, vp
);
2074 if (p
&& p
->p_stats
)
2075 OSIncrementAtomicLong(&p
->p_stats
->p_ru
.ru_oublock
); /* XXX */
2077 trace(TR_BUFWRITE
, pack(vp
, bp
->b_bcount
), bp
->b_lblkno
);
2079 /* Initiate disk write. Make sure the appropriate party is charged. */
2081 OSAddAtomic(1, &vp
->v_numoutput
);
2087 * If I/O was synchronous, wait for it to complete.
2089 rv
= buf_biowait(bp
);
2092 * Pay for the I/O operation, if it's not been paid for, and
2093 * make sure it's on the correct vnode queue. (async operatings
2094 * were payed for above.)
2097 buf_reassign(bp
, vp
);
2099 if (p
&& p
->p_stats
)
2100 OSIncrementAtomicLong(&p
->p_stats
->p_ru
.ru_oublock
); /* XXX */
2102 /* Release the buffer. */
2103 // XXXdbg - only if the unused bit is set
2104 if (!ISSET(bp
->b_flags
, B_NORELSE
)) {
2107 CLR(bp
->b_flags
, B_NORELSE
);
2117 vn_bwrite(struct vnop_bwrite_args
*ap
)
2119 return (buf_bwrite(ap
->a_bp
));
2125 * The buffer is marked dirty, but is not queued for I/O.
2126 * This routine should be used when the buffer is expected
2127 * to be modified again soon, typically a small write that
2128 * partially fills a buffer.
2130 * NB: magnetic tapes cannot be delayed; they must be
2131 * written in the order that the writes are requested.
2133 * Described in Leffler, et al. (pp. 208-213).
2135 * Note: With the ability to allocate additional buffer
2136 * headers, we can get in to the situation where "too" many
2137 * buf_bdwrite()s can create situation where the kernel can create
2138 * buffers faster than the disks can service. Doing a buf_bawrite() in
2139 * cases where we have "too many" outstanding buf_bdwrite()s avoids that.
2141 __private_extern__
int
2142 bdwrite_internal(buf_t bp
, int return_error
)
2144 proc_t p
= current_proc();
2145 vnode_t vp
= bp
->b_vp
;
2148 * If the block hasn't been seen before:
2149 * (1) Mark it as having been seen,
2150 * (2) Charge for the write.
2151 * (3) Make sure it's on its vnode's correct block list,
2153 if (!ISSET(bp
->b_flags
, B_DELWRI
)) {
2154 SET(bp
->b_flags
, B_DELWRI
);
2155 if (p
&& p
->p_stats
)
2156 OSIncrementAtomicLong(&p
->p_stats
->p_ru
.ru_oublock
); /* XXX */
2157 OSAddAtomicLong(1, &nbdwrite
);
2158 buf_reassign(bp
, vp
);
2162 * if we're not LOCKED, but the total number of delayed writes
2163 * has climbed above 75% of the total buffers in the system
2164 * return an error if the caller has indicated that it can
2165 * handle one in this case, otherwise schedule the I/O now
2166 * this is done to prevent us from allocating tons of extra
2167 * buffers when dealing with virtual disks (i.e. DiskImages),
2168 * because additional buffers are dynamically allocated to prevent
2169 * deadlocks from occurring
2171 * however, can't do a buf_bawrite() if the LOCKED bit is set because the
2172 * buffer is part of a transaction and can't go to disk until
2173 * the LOCKED bit is cleared.
2175 if (!ISSET(bp
->b_flags
, B_LOCKED
) && nbdwrite
> ((nbuf_headers
/4)*3)) {
2179 * If the vnode has "too many" write operations in progress
2180 * wait for them to finish the IO
2182 (void)vnode_waitforwrites(vp
, VNODE_ASYNC_THROTTLE
, 0, 0, "buf_bdwrite");
2184 return (buf_bawrite(bp
));
2187 /* Otherwise, the "write" is done, so mark and release the buffer. */
2188 SET(bp
->b_flags
, B_DONE
);
2194 buf_bdwrite(buf_t bp
)
2196 return (bdwrite_internal(bp
, 0));
2201 * Asynchronous block write; just an asynchronous buf_bwrite().
2203 * Note: With the abilitty to allocate additional buffer
2204 * headers, we can get in to the situation where "too" many
2205 * buf_bawrite()s can create situation where the kernel can create
2206 * buffers faster than the disks can service.
2207 * We limit the number of "in flight" writes a vnode can have to
2211 bawrite_internal(buf_t bp
, int throttle
)
2213 vnode_t vp
= bp
->b_vp
;
2218 * If the vnode has "too many" write operations in progress
2219 * wait for them to finish the IO
2221 (void)vnode_waitforwrites(vp
, VNODE_ASYNC_THROTTLE
, 0, 0, (const char *)"buf_bawrite");
2222 else if (vp
->v_numoutput
>= VNODE_ASYNC_THROTTLE
)
2224 * return to the caller and
2225 * let him decide what to do
2227 return (EWOULDBLOCK
);
2229 SET(bp
->b_flags
, B_ASYNC
);
2231 return (VNOP_BWRITE(bp
));
2235 buf_bawrite(buf_t bp
)
2237 return (bawrite_internal(bp
, 1));
2243 buf_free_meta_store(buf_t bp
)
2245 if (bp
->b_bufsize
) {
2246 if (ISSET(bp
->b_flags
, B_ZALLOC
)) {
2249 z
= getbufzone(bp
->b_bufsize
);
2250 zfree(z
, (void *)bp
->b_datap
);
2252 kmem_free(kernel_map
, bp
->b_datap
, bp
->b_bufsize
);
2254 bp
->b_datap
= (uintptr_t)NULL
;
2261 buf_brelse_shadow(buf_t bp
)
2265 buf_t bp_return
= NULL
;
2266 #ifdef BUF_MAKE_PRIVATE
2270 lck_mtx_lock_spin(buf_mtxp
);
2272 bp_head
= (buf_t
)bp
->b_orig
;
2274 if (bp_head
->b_whichq
!= -1)
2275 panic("buf_brelse_shadow: bp_head on freelist %d\n", bp_head
->b_whichq
);
2277 #ifdef BUF_MAKE_PRIVATE
2278 if (bp_data
= bp
->b_data_store
) {
2279 bp_data
->b_data_ref
--;
2281 * snapshot the ref count so that we can check it
2282 * outside of the lock... we only want the guy going
2283 * from 1 -> 0 to try and release the storage
2285 data_ref
= bp_data
->b_data_ref
;
2288 KERNEL_DEBUG(0xbbbbc008 | DBG_FUNC_START
, bp
, bp_head
, bp_head
->b_shadow_ref
, 0, 0);
2290 bp_head
->b_shadow_ref
--;
2292 for (bp_temp
= bp_head
; bp_temp
&& bp
!= bp_temp
->b_shadow
; bp_temp
= bp_temp
->b_shadow
);
2294 if (bp_temp
== NULL
)
2295 panic("buf_brelse_shadow: bp not on list %p", bp_head
);
2297 bp_temp
->b_shadow
= bp_temp
->b_shadow
->b_shadow
;
2299 #ifdef BUF_MAKE_PRIVATE
2301 * we're about to free the current 'owner' of the data buffer and
2302 * there is at least one other shadow buf_t still pointing at it
2303 * so transfer it to the first shadow buf left in the chain
2305 if (bp
== bp_data
&& data_ref
) {
2306 if ((bp_data
= bp_head
->b_shadow
) == NULL
)
2307 panic("buf_brelse_shadow: data_ref mismatch bp(%p)", bp
);
2309 for (bp_temp
= bp_data
; bp_temp
; bp_temp
= bp_temp
->b_shadow
)
2310 bp_temp
->b_data_store
= bp_data
;
2311 bp_data
->b_data_ref
= data_ref
;
2314 if (bp_head
->b_shadow_ref
== 0 && bp_head
->b_shadow
)
2315 panic("buf_relse_shadow: b_shadow != NULL && b_shadow_ref == 0 bp(%p)", bp
);
2316 if (bp_head
->b_shadow_ref
&& bp_head
->b_shadow
== 0)
2317 panic("buf_relse_shadow: b_shadow == NULL && b_shadow_ref != 0 bp(%p)", bp
);
2319 if (bp_head
->b_shadow_ref
== 0) {
2320 if (!ISSET(bp_head
->b_lflags
, BL_BUSY
)) {
2322 CLR(bp_head
->b_flags
, B_AGE
);
2323 bp_head
->b_timestamp
= buf_timestamp();
2325 if (ISSET(bp_head
->b_flags
, B_LOCKED
)) {
2326 bp_head
->b_whichq
= BQ_LOCKED
;
2327 binstailfree(bp_head
, &bufqueues
[BQ_LOCKED
], BQ_LOCKED
);
2329 bp_head
->b_whichq
= BQ_META
;
2330 binstailfree(bp_head
, &bufqueues
[BQ_META
], BQ_META
);
2332 } else if (ISSET(bp_head
->b_lflags
, BL_WAITSHADOW
)) {
2333 CLR(bp_head
->b_lflags
, BL_WAITSHADOW
);
2335 bp_return
= bp_head
;
2338 lck_mtx_unlock(buf_mtxp
);
2339 #ifdef BUF_MAKE_PRIVATE
2340 if (bp
== bp_data
&& data_ref
== 0)
2341 buf_free_meta_store(bp
);
2343 bp
->b_data_store
= NULL
;
2345 KERNEL_DEBUG(0xbbbbc008 | DBG_FUNC_END
, bp
, 0, 0, 0, 0);
2352 * Release a buffer on to the free lists.
2353 * Described in Bach (p. 46).
2356 buf_brelse(buf_t bp
)
2358 struct bqueues
*bufq
;
2361 int need_wakeup
= 0;
2362 int need_bp_wakeup
= 0;
2365 if (bp
->b_whichq
!= -1 || !(bp
->b_lflags
& BL_BUSY
))
2366 panic("buf_brelse: bad buffer = %p\n", bp
);
2369 (void) OSBacktrace(&bp
->b_stackbrelse
[0], 6);
2371 bp
->b_lastbrelse
= current_thread();
2374 if (bp
->b_lflags
& BL_IOBUF
) {
2375 buf_t shadow_master_bp
= NULL
;
2377 if (ISSET(bp
->b_lflags
, BL_SHADOW
))
2378 shadow_master_bp
= buf_brelse_shadow(bp
);
2379 else if (ISSET(bp
->b_lflags
, BL_IOBUF_ALLOC
))
2380 buf_free_meta_store(bp
);
2383 if (shadow_master_bp
) {
2384 bp
= shadow_master_bp
;
2385 goto finish_shadow_master
;
2390 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW
, 388)) | DBG_FUNC_START
,
2391 bp
->b_lblkno
* PAGE_SIZE
, bp
, bp
->b_datap
,
2394 trace(TR_BRELSE
, pack(bp
->b_vp
, bp
->b_bufsize
), bp
->b_lblkno
);
2397 * if we're invalidating a buffer that has the B_FILTER bit
2398 * set then call the b_iodone function so it gets cleaned
2401 * the HFS journal code depends on this
2403 if (ISSET(bp
->b_flags
, B_META
) && ISSET(bp
->b_flags
, B_INVAL
)) {
2404 if (ISSET(bp
->b_flags
, B_FILTER
)) { /* if necessary, call out */
2405 void (*iodone_func
)(struct buf
*, void *) = bp
->b_iodone
;
2406 void *arg
= bp
->b_transaction
;
2408 CLR(bp
->b_flags
, B_FILTER
); /* but note callout done */
2409 bp
->b_iodone
= NULL
;
2410 bp
->b_transaction
= NULL
;
2412 if (iodone_func
== NULL
) {
2413 panic("brelse: bp @ %p has NULL b_iodone!\n", bp
);
2415 (*iodone_func
)(bp
, arg
);
2419 * I/O is done. Cleanup the UPL state
2423 if ( !ISSET(bp
->b_flags
, B_META
) && UBCINFOEXISTS(bp
->b_vp
) && bp
->b_bufsize
) {
2428 if ( !ISSET(bp
->b_flags
, B_INVAL
)) {
2429 kret
= ubc_create_upl(bp
->b_vp
,
2430 ubc_blktooff(bp
->b_vp
, bp
->b_lblkno
),
2436 if (kret
!= KERN_SUCCESS
)
2437 panic("brelse: Failed to create UPL");
2439 upl_ubc_alias_set(upl
, (uintptr_t) bp
, (uintptr_t) 5);
2440 #endif /* UPL_DEBUG */
2444 kret
= ubc_upl_unmap(upl
);
2446 if (kret
!= KERN_SUCCESS
)
2447 panic("ubc_upl_unmap failed");
2448 bp
->b_datap
= (uintptr_t)NULL
;
2452 if (bp
->b_flags
& (B_ERROR
| B_INVAL
)) {
2453 if (bp
->b_flags
& (B_READ
| B_INVAL
))
2454 upl_flags
= UPL_ABORT_DUMP_PAGES
;
2458 ubc_upl_abort(upl
, upl_flags
);
2460 if (ISSET(bp
->b_flags
, B_DELWRI
| B_WASDIRTY
))
2461 upl_flags
= UPL_COMMIT_SET_DIRTY
;
2463 upl_flags
= UPL_COMMIT_CLEAR_DIRTY
;
2465 ubc_upl_commit_range(upl
, 0, bp
->b_bufsize
, upl_flags
|
2466 UPL_COMMIT_INACTIVATE
| UPL_COMMIT_FREE_ON_EMPTY
);
2472 panic("brelse: UPL set for non VREG; vp=%p", bp
->b_vp
);
2476 * If it's locked, don't report an error; try again later.
2478 if (ISSET(bp
->b_flags
, (B_LOCKED
|B_ERROR
)) == (B_LOCKED
|B_ERROR
))
2479 CLR(bp
->b_flags
, B_ERROR
);
2481 * If it's not cacheable, or an error, mark it invalid.
2483 if (ISSET(bp
->b_flags
, (B_NOCACHE
|B_ERROR
)))
2484 SET(bp
->b_flags
, B_INVAL
);
2486 if ((bp
->b_bufsize
<= 0) ||
2487 ISSET(bp
->b_flags
, B_INVAL
) ||
2488 (ISSET(bp
->b_lflags
, BL_WANTDEALLOC
) && !ISSET(bp
->b_flags
, B_DELWRI
))) {
2490 boolean_t delayed_buf_free_meta_store
= FALSE
;
2493 * If it's invalid or empty, dissociate it from its vnode,
2494 * release its storage if B_META, and
2495 * clean it up a bit and put it on the EMPTY queue
2497 if (ISSET(bp
->b_flags
, B_DELWRI
))
2498 OSAddAtomicLong(-1, &nbdwrite
);
2500 if (ISSET(bp
->b_flags
, B_META
)) {
2501 if (bp
->b_shadow_ref
)
2502 delayed_buf_free_meta_store
= TRUE
;
2504 buf_free_meta_store(bp
);
2507 * nuke any credentials we were holding
2509 buf_release_credentials(bp
);
2511 lck_mtx_lock_spin(buf_mtxp
);
2513 if (bp
->b_shadow_ref
) {
2514 SET(bp
->b_lflags
, BL_WAITSHADOW
);
2516 lck_mtx_unlock(buf_mtxp
);
2520 if (delayed_buf_free_meta_store
== TRUE
) {
2522 lck_mtx_unlock(buf_mtxp
);
2523 finish_shadow_master
:
2524 buf_free_meta_store(bp
);
2526 lck_mtx_lock_spin(buf_mtxp
);
2528 CLR(bp
->b_flags
, (B_META
| B_ZALLOC
| B_DELWRI
| B_LOCKED
| B_AGE
| B_ASYNC
| B_NOCACHE
| B_FUA
));
2535 binshash(bp
, &invalhash
);
2537 bp
->b_whichq
= BQ_EMPTY
;
2538 binsheadfree(bp
, &bufqueues
[BQ_EMPTY
], BQ_EMPTY
);
2542 * It has valid data. Put it on the end of the appropriate
2543 * queue, so that it'll stick around for as long as possible.
2545 if (ISSET(bp
->b_flags
, B_LOCKED
))
2546 whichq
= BQ_LOCKED
; /* locked in core */
2547 else if (ISSET(bp
->b_flags
, B_META
))
2548 whichq
= BQ_META
; /* meta-data */
2549 else if (ISSET(bp
->b_flags
, B_AGE
))
2550 whichq
= BQ_AGE
; /* stale but valid data */
2552 whichq
= BQ_LRU
; /* valid data */
2553 bufq
= &bufqueues
[whichq
];
2555 bp
->b_timestamp
= buf_timestamp();
2557 lck_mtx_lock_spin(buf_mtxp
);
2560 * the buf_brelse_shadow routine doesn't take 'ownership'
2561 * of the parent buf_t... it updates state that is protected by
2562 * the buf_mtxp, and checks for BL_BUSY to determine whether to
2563 * put the buf_t back on a free list. b_shadow_ref is protected
2564 * by the lock, and since we have not yet cleared B_BUSY, we need
2565 * to check it while holding the lock to insure that one of us
2566 * puts this buf_t back on a free list when it is safe to do so
2568 if (bp
->b_shadow_ref
== 0) {
2569 CLR(bp
->b_flags
, (B_AGE
| B_ASYNC
| B_NOCACHE
));
2570 bp
->b_whichq
= whichq
;
2571 binstailfree(bp
, bufq
, whichq
);
2574 * there are still cloned buf_t's pointing
2575 * at this guy... need to keep it off the
2576 * freelists until a buf_brelse is done on
2579 CLR(bp
->b_flags
, (B_ASYNC
| B_NOCACHE
));
2584 * needbuffer is a global
2585 * we're currently using buf_mtxp to protect it
2586 * delay doing the actual wakeup until after
2592 if (ISSET(bp
->b_lflags
, BL_WANTED
)) {
2594 * delay the actual wakeup until after we
2595 * clear BL_BUSY and we've dropped buf_mtxp
2600 * Unlock the buffer.
2602 CLR(bp
->b_lflags
, (BL_BUSY
| BL_WANTED
));
2605 lck_mtx_unlock(buf_mtxp
);
2609 * Wake up any processes waiting for any buffer to become free.
2611 wakeup(&needbuffer
);
2613 if (need_bp_wakeup
) {
2615 * Wake up any proceeses waiting for _this_ buffer to become free.
2619 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW
, 388)) | DBG_FUNC_END
,
2620 bp
, bp
->b_datap
, bp
->b_flags
, 0, 0);
2624 * Determine if a block is in the cache.
2625 * Just look on what would be its hash chain. If it's there, return
2626 * a pointer to it, unless it's marked invalid. If it's marked invalid,
2627 * we normally don't return the buffer, unless the caller explicitly
2631 incore(vnode_t vp
, daddr64_t blkno
)
2634 struct bufhashhdr
*dp
;
2636 dp
= BUFHASH(vp
, blkno
);
2638 lck_mtx_lock_spin(buf_mtxp
);
2640 if (incore_locked(vp
, blkno
, dp
))
2644 lck_mtx_unlock(buf_mtxp
);
2651 incore_locked(vnode_t vp
, daddr64_t blkno
, struct bufhashhdr
*dp
)
2655 /* Search hash chain */
2656 for (bp
= dp
->lh_first
; bp
!= NULL
; bp
= bp
->b_hash
.le_next
) {
2657 if (bp
->b_lblkno
== blkno
&& bp
->b_vp
== vp
&&
2658 !ISSET(bp
->b_flags
, B_INVAL
)) {
2666 /* XXX FIXME -- Update the comment to reflect the UBC changes (please) -- */
2668 * Get a block of requested size that is associated with
2669 * a given vnode and block offset. If it is found in the
2670 * block cache, mark it as having been found, make it busy
2671 * and return it. Otherwise, return an empty block of the
2672 * correct size. It is up to the caller to insure that the
2673 * cached blocks be of the correct size.
2676 buf_getblk(vnode_t vp
, daddr64_t blkno
, int size
, int slpflag
, int slptimeo
, int operation
)
2681 upl_page_info_t
*pl
;
2686 struct bufhashhdr
*dp
;
2688 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW
, 386)) | DBG_FUNC_START
,
2689 (uintptr_t)(blkno
* PAGE_SIZE
), size
, operation
, 0, 0);
2691 ret_only_valid
= operation
& BLK_ONLYVALID
;
2692 operation
&= ~BLK_ONLYVALID
;
2693 dp
= BUFHASH(vp
, blkno
);
2695 lck_mtx_lock_spin(buf_mtxp
);
2697 if ((bp
= incore_locked(vp
, blkno
, dp
))) {
2699 * Found in the Buffer Cache
2701 if (ISSET(bp
->b_lflags
, BL_BUSY
)) {
2705 switch (operation
) {
2709 SET(bp
->b_lflags
, BL_WANTED
);
2710 bufstats
.bufs_busyincore
++;
2713 * don't retake the mutex after being awakened...
2714 * the time out is in msecs
2716 ts
.tv_sec
= (slptimeo
/1000);
2717 ts
.tv_nsec
= (slptimeo
% 1000) * 10 * NSEC_PER_USEC
* 1000;
2719 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW
, 396)) | DBG_FUNC_NONE
,
2720 (uintptr_t)blkno
, size
, operation
, 0, 0);
2722 err
= msleep(bp
, buf_mtxp
, slpflag
| PDROP
| (PRIBIO
+ 1), "buf_getblk", &ts
);
2725 * Callers who call with PCATCH or timeout are
2726 * willing to deal with the NULL pointer
2728 if (err
&& ((slpflag
& PCATCH
) || ((err
== EWOULDBLOCK
) && slptimeo
)))
2736 * unknown operation requested
2738 panic("getblk: paging or unknown operation for incore busy buffer - %x\n", operation
);
2744 * buffer in core and not busy
2746 SET(bp
->b_lflags
, BL_BUSY
);
2747 SET(bp
->b_flags
, B_CACHE
);
2750 bremfree_locked(bp
);
2751 bufstats
.bufs_incore
++;
2753 lck_mtx_unlock(buf_mtxp
);
2755 bp
->b_owner
= current_thread();
2759 panic("buffer has UPL, but not marked BUSY: %p", bp
);
2761 if ( !ret_only_valid
&& bp
->b_bufsize
!= size
)
2765 switch (operation
) {
2768 * "write" operation: let the UPL subsystem
2769 * know that we intend to modify the buffer
2770 * cache pages we're gathering.
2772 upl_flags
|= UPL_WILL_MODIFY
;
2774 upl_flags
|= UPL_PRECIOUS
;
2775 if (UBCINFOEXISTS(bp
->b_vp
) && bp
->b_bufsize
) {
2776 kret
= ubc_create_upl(vp
,
2777 ubc_blktooff(vp
, bp
->b_lblkno
),
2782 if (kret
!= KERN_SUCCESS
)
2783 panic("Failed to create UPL");
2787 if (upl_valid_page(pl
, 0)) {
2788 if (upl_dirty_page(pl
, 0))
2789 SET(bp
->b_flags
, B_WASDIRTY
);
2791 CLR(bp
->b_flags
, B_WASDIRTY
);
2793 CLR(bp
->b_flags
, (B_DONE
| B_CACHE
| B_WASDIRTY
| B_DELWRI
));
2795 kret
= ubc_upl_map(upl
, (vm_offset_t
*)&(bp
->b_datap
));
2797 if (kret
!= KERN_SUCCESS
)
2798 panic("getblk: ubc_upl_map() failed with (%d)", kret
);
2804 * VM is not involved in IO for the meta data
2805 * buffer already has valid data
2810 panic("getblk: paging or unknown operation for incore buffer- %d\n", operation
);
2815 } else { /* not incore() */
2816 int queue
= BQ_EMPTY
; /* Start with no preference */
2818 if (ret_only_valid
) {
2819 lck_mtx_unlock(buf_mtxp
);
2822 if ((vnode_isreg(vp
) == 0) || (UBCINFOEXISTS(vp
) == 0) /*|| (vnode_issystem(vp) == 1)*/)
2823 operation
= BLK_META
;
2825 if ((bp
= getnewbuf(slpflag
, slptimeo
, &queue
)) == NULL
)
2829 * getnewbuf may block for a number of different reasons...
2830 * if it does, it's then possible for someone else to
2831 * create a buffer for the same block and insert it into
2832 * the hash... if we see it incore at this point we dump
2833 * the buffer we were working on and start over
2835 if (incore_locked(vp
, blkno
, dp
)) {
2836 SET(bp
->b_flags
, B_INVAL
);
2837 binshash(bp
, &invalhash
);
2839 lck_mtx_unlock(buf_mtxp
);
2845 * NOTE: YOU CAN NOT BLOCK UNTIL binshash() HAS BEEN
2846 * CALLED! BE CAREFUL.
2850 * mark the buffer as B_META if indicated
2851 * so that when buffer is released it will goto META queue
2853 if (operation
== BLK_META
)
2854 SET(bp
->b_flags
, B_META
);
2856 bp
->b_blkno
= bp
->b_lblkno
= blkno
;
2860 * Insert in the hash so that incore() can find it
2862 binshash(bp
, BUFHASH(vp
, blkno
));
2864 bgetvp_locked(vp
, bp
);
2866 lck_mtx_unlock(buf_mtxp
);
2871 switch (operation
) {
2874 * buffer data is invalid...
2876 * I don't want to have to retake buf_mtxp,
2877 * so the miss and vmhits counters are done
2878 * with Atomic updates... all other counters
2879 * in bufstats are protected with either
2880 * buf_mtxp or iobuffer_mtxp
2882 OSAddAtomicLong(1, &bufstats
.bufs_miss
);
2887 * "write" operation: let the UPL subsystem know
2888 * that we intend to modify the buffer cache pages
2891 upl_flags
|= UPL_WILL_MODIFY
;
2894 size_t contig_bytes
;
2898 panic("bp already has UPL: %p",bp
);
2900 f_offset
= ubc_blktooff(vp
, blkno
);
2902 upl_flags
|= UPL_PRECIOUS
;
2903 kret
= ubc_create_upl(vp
,
2910 if (kret
!= KERN_SUCCESS
)
2911 panic("Failed to create UPL");
2913 upl_ubc_alias_set(upl
, (uintptr_t) bp
, (uintptr_t) 4);
2914 #endif /* UPL_DEBUG */
2917 if (upl_valid_page(pl
, 0)) {
2919 if (operation
== BLK_READ
)
2920 bmap_flags
= VNODE_READ
;
2922 bmap_flags
= VNODE_WRITE
;
2924 SET(bp
->b_flags
, B_CACHE
| B_DONE
);
2926 OSAddAtomicLong(1, &bufstats
.bufs_vmhits
);
2931 if (upl_dirty_page(pl
, 0)) {
2933 SET(bp
->b_flags
, B_WASDIRTY
);
2935 bp
->b_validend
= bp
->b_bcount
;
2936 bp
->b_dirtyend
= bp
->b_bcount
;
2939 bp
->b_validend
= bp
->b_bcount
;
2943 * try to recreate the physical block number associated with
2946 if (VNOP_BLOCKMAP(vp
, f_offset
, bp
->b_bcount
, &bp
->b_blkno
, &contig_bytes
, NULL
, bmap_flags
, NULL
))
2947 panic("getblk: VNOP_BLOCKMAP failed");
2949 * if the extent represented by this buffer
2950 * is not completely physically contiguous on
2951 * disk, than we can't cache the physical mapping
2952 * in the buffer header
2954 if ((long)contig_bytes
< bp
->b_bcount
)
2955 bp
->b_blkno
= bp
->b_lblkno
;
2957 OSAddAtomicLong(1, &bufstats
.bufs_miss
);
2959 kret
= ubc_upl_map(upl
, (vm_offset_t
*)&(bp
->b_datap
));
2961 if (kret
!= KERN_SUCCESS
)
2962 panic("getblk: ubc_upl_map() failed with (%d)", kret
);
2966 panic("getblk: paging or unknown operation - %x", operation
);
2971 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW
, 386)) | DBG_FUNC_END
,
2972 bp
, bp
->b_datap
, bp
->b_flags
, 3, 0);
2975 (void) OSBacktrace(&bp
->b_stackgetblk
[0], 6);
2981 * Get an empty, disassociated buffer of given size.
2984 buf_geteblk(int size
)
2987 int queue
= BQ_EMPTY
;
2990 lck_mtx_lock_spin(buf_mtxp
);
2992 bp
= getnewbuf(0, 0, &queue
);
2993 } while (bp
== NULL
);
2995 SET(bp
->b_flags
, (B_META
|B_INVAL
));
2998 assert(queue
== BQ_EMPTY
);
2999 #endif /* DIAGNOSTIC */
3000 /* XXX need to implement logic to deal with other queues */
3002 binshash(bp
, &invalhash
);
3003 bufstats
.bufs_eblk
++;
3005 lck_mtx_unlock(buf_mtxp
);
3013 buf_redundancy_flags(buf_t bp
)
3015 return bp
->b_redundancy_flags
;
3019 buf_set_redundancy_flags(buf_t bp
, uint32_t flags
)
3021 SET(bp
->b_redundancy_flags
, flags
);
3025 buf_clear_redundancy_flags(buf_t bp
, uint32_t flags
)
3027 CLR(bp
->b_redundancy_flags
, flags
);
3031 * With UBC, there is no need to expand / shrink the file data
3032 * buffer. The VM uses the same pages, hence no waste.
3033 * All the file data buffers can have one size.
3034 * In fact expand / shrink would be an expensive operation.
3036 * Only exception to this is meta-data buffers. Most of the
3037 * meta data operations are smaller than PAGE_SIZE. Having the
3038 * meta-data buffers grow and shrink as needed, optimizes use
3039 * of the kernel wired memory.
3043 allocbuf(buf_t bp
, int size
)
3045 vm_size_t desired_size
;
3047 desired_size
= roundup(size
, CLBYTES
);
3049 if (desired_size
< PAGE_SIZE
)
3050 desired_size
= PAGE_SIZE
;
3051 if (desired_size
> MAXBSIZE
)
3052 panic("allocbuf: buffer larger than MAXBSIZE requested");
3054 if (ISSET(bp
->b_flags
, B_META
)) {
3056 int nsize
= roundup(size
, MINMETA
);
3059 vm_offset_t elem
= (vm_offset_t
)bp
->b_datap
;
3061 if (ISSET(bp
->b_flags
, B_ZALLOC
)) {
3062 if (bp
->b_bufsize
< nsize
) {
3063 /* reallocate to a bigger size */
3065 zprev
= getbufzone(bp
->b_bufsize
);
3066 if (nsize
<= MAXMETA
) {
3067 desired_size
= nsize
;
3068 z
= getbufzone(nsize
);
3069 /* b_datap not really a ptr */
3070 *(void **)(&bp
->b_datap
) = zalloc(z
);
3072 bp
->b_datap
= (uintptr_t)NULL
;
3073 kmem_alloc_kobject(kernel_map
, (vm_offset_t
*)&bp
->b_datap
, desired_size
);
3074 CLR(bp
->b_flags
, B_ZALLOC
);
3076 bcopy((void *)elem
, (caddr_t
)bp
->b_datap
, bp
->b_bufsize
);
3077 zfree(zprev
, (void *)elem
);
3079 desired_size
= bp
->b_bufsize
;
3083 if ((vm_size_t
)bp
->b_bufsize
< desired_size
) {
3084 /* reallocate to a bigger size */
3085 bp
->b_datap
= (uintptr_t)NULL
;
3086 kmem_alloc_kobject(kernel_map
, (vm_offset_t
*)&bp
->b_datap
, desired_size
);
3087 bcopy((const void *)elem
, (caddr_t
)bp
->b_datap
, bp
->b_bufsize
);
3088 kmem_free(kernel_map
, elem
, bp
->b_bufsize
);
3090 desired_size
= bp
->b_bufsize
;
3094 /* new allocation */
3095 if (nsize
<= MAXMETA
) {
3096 desired_size
= nsize
;
3097 z
= getbufzone(nsize
);
3098 /* b_datap not really a ptr */
3099 *(void **)(&bp
->b_datap
) = zalloc(z
);
3100 SET(bp
->b_flags
, B_ZALLOC
);
3102 kmem_alloc_kobject(kernel_map
, (vm_offset_t
*)&bp
->b_datap
, desired_size
);
3105 if (bp
->b_datap
== 0)
3106 panic("allocbuf: NULL b_datap");
3108 bp
->b_bufsize
= desired_size
;
3109 bp
->b_bcount
= size
;
3115 * Get a new buffer from one of the free lists.
3117 * Request for a queue is passes in. The queue from which the buffer was taken
3118 * from is returned. Out of range queue requests get BQ_EMPTY. Request for
3119 * BQUEUE means no preference. Use heuristics in that case.
3120 * Heuristics is as follows:
3121 * Try BQ_AGE, BQ_LRU, BQ_EMPTY, BQ_META in that order.
3122 * If none available block till one is made available.
3123 * If buffers available on both BQ_AGE and BQ_LRU, check the timestamps.
3124 * Pick the most stale buffer.
3125 * If found buffer was marked delayed write, start the async. write
3126 * and restart the search.
3127 * Initialize the fields and disassociate the buffer from the vnode.
3128 * Remove the buffer from the hash. Return the buffer and the queue
3129 * on which it was found.
3131 * buf_mtxp is held upon entry
3132 * returns with buf_mtxp locked if new buf available
3133 * returns with buf_mtxp UNlocked if new buf NOT available
3137 getnewbuf(int slpflag
, int slptimeo
, int * queue
)
3143 int age_time
, lru_time
, bp_time
, meta_time
;
3144 int req
= *queue
; /* save it for restarts */
3149 * invalid request gets empty queue
3151 if ((*queue
>= BQUEUES
) || (*queue
< 0)
3152 || (*queue
== BQ_LAUNDRY
) || (*queue
== BQ_LOCKED
))
3156 if (*queue
== BQ_EMPTY
&& (bp
= bufqueues
[*queue
].tqh_first
))
3160 * need to grow number of bufs, add another one rather than recycling
3162 if (nbuf_headers
< max_nbuf_headers
) {
3164 * Increment count now as lock
3165 * is dropped for allocation.
3166 * That avoids over commits
3171 /* Try for the requested queue first */
3172 bp
= bufqueues
[*queue
].tqh_first
;
3176 /* Unable to use requested queue */
3177 age_bp
= bufqueues
[BQ_AGE
].tqh_first
;
3178 lru_bp
= bufqueues
[BQ_LRU
].tqh_first
;
3179 meta_bp
= bufqueues
[BQ_META
].tqh_first
;
3181 if (!age_bp
&& !lru_bp
&& !meta_bp
) {
3183 * Unavailble on AGE or LRU or META queues
3184 * Try the empty list first
3186 bp
= bufqueues
[BQ_EMPTY
].tqh_first
;
3192 * We have seen is this is hard to trigger.
3193 * This is an overcommit of nbufs but needed
3194 * in some scenarios with diskiamges
3198 lck_mtx_unlock(buf_mtxp
);
3200 /* Create a new temporary buffer header */
3201 bp
= (struct buf
*)zalloc(buf_hdr_zone
);
3205 bp
->b_whichq
= BQ_EMPTY
;
3206 bp
->b_timestamp
= buf_timestamp();
3208 SET(bp
->b_flags
, B_HDRALLOC
);
3211 lck_mtx_lock_spin(buf_mtxp
);
3214 binshash(bp
, &invalhash
);
3215 binsheadfree(bp
, &bufqueues
[BQ_EMPTY
], BQ_EMPTY
);
3219 /* subtract already accounted bufcount */
3222 bufstats
.bufs_sleeps
++;
3224 /* wait for a free buffer of any kind */
3226 /* hz value is 100 */
3227 ts
.tv_sec
= (slptimeo
/1000);
3228 /* the hz value is 100; which leads to 10ms */
3229 ts
.tv_nsec
= (slptimeo
% 1000) * NSEC_PER_USEC
* 1000 * 10;
3231 msleep(&needbuffer
, buf_mtxp
, slpflag
| PDROP
| (PRIBIO
+1), "getnewbuf", &ts
);
3235 /* Buffer available either on AGE or LRU or META */
3239 /* Buffer available either on AGE or LRU */
3243 } else if (!lru_bp
) {
3246 } else { /* buffer available on both AGE and LRU */
3247 int t
= buf_timestamp();
3249 age_time
= t
- age_bp
->b_timestamp
;
3250 lru_time
= t
- lru_bp
->b_timestamp
;
3251 if ((age_time
< 0) || (lru_time
< 0)) { /* time set backwards */
3255 * we should probably re-timestamp eveything in the
3256 * queues at this point with the current time
3259 if ((lru_time
>= lru_is_stale
) && (age_time
< age_is_stale
)) {
3269 if (!bp
) { /* Neither on AGE nor on LRU */
3272 } else if (meta_bp
) {
3273 int t
= buf_timestamp();
3275 bp_time
= t
- bp
->b_timestamp
;
3276 meta_time
= t
- meta_bp
->b_timestamp
;
3278 if (!(bp_time
< 0) && !(meta_time
< 0)) {
3279 /* time not set backwards */
3281 bp_is_stale
= (*queue
== BQ_LRU
) ?
3282 lru_is_stale
: age_is_stale
;
3284 if ((meta_time
>= meta_is_stale
) &&
3285 (bp_time
< bp_is_stale
)) {
3292 if (ISSET(bp
->b_flags
, B_LOCKED
) || ISSET(bp
->b_lflags
, BL_BUSY
))
3293 panic("getnewbuf: bp @ %p is LOCKED or BUSY! (flags 0x%x)\n", bp
, bp
->b_flags
);
3296 if (bcleanbuf(bp
, FALSE
)) {
3298 * moved to the laundry thread, buffer not ready
3309 * Returns 0 if buffer is ready to use,
3310 * Returns 1 if issued a buf_bawrite() to indicate
3311 * that the buffer is not ready.
3313 * buf_mtxp is held upon entry
3314 * returns with buf_mtxp locked
3317 bcleanbuf(buf_t bp
, boolean_t discard
)
3319 /* Remove from the queue */
3320 bremfree_locked(bp
);
3323 bp
->b_owner
= current_thread();
3327 * If buffer was a delayed write, start the IO by queuing
3328 * it on the LAUNDRY queue, and return 1
3330 if (ISSET(bp
->b_flags
, B_DELWRI
)) {
3332 SET(bp
->b_lflags
, BL_WANTDEALLOC
);
3337 lck_mtx_unlock(buf_mtxp
);
3339 wakeup(&bufqueues
[BQ_LAUNDRY
]);
3341 * and give it a chance to run
3343 (void)thread_block(THREAD_CONTINUE_NULL
);
3345 lck_mtx_lock_spin(buf_mtxp
);
3350 bp
->b_owner
= current_thread();
3354 * Buffer is no longer on any free list... we own it
3356 SET(bp
->b_lflags
, BL_BUSY
);
3362 * disassociate us from our vnode, if we had one...
3367 lck_mtx_unlock(buf_mtxp
);
3371 if (ISSET(bp
->b_flags
, B_META
))
3372 buf_free_meta_store(bp
);
3374 trace(TR_BRELSE
, pack(bp
->b_vp
, bp
->b_bufsize
), bp
->b_lblkno
);
3376 buf_release_credentials(bp
);
3378 /* If discarding, just move to the empty queue */
3380 lck_mtx_lock_spin(buf_mtxp
);
3381 CLR(bp
->b_flags
, (B_META
| B_ZALLOC
| B_DELWRI
| B_LOCKED
| B_AGE
| B_ASYNC
| B_NOCACHE
| B_FUA
));
3382 bp
->b_whichq
= BQ_EMPTY
;
3383 binshash(bp
, &invalhash
);
3384 binsheadfree(bp
, &bufqueues
[BQ_EMPTY
], BQ_EMPTY
);
3385 CLR(bp
->b_lflags
, BL_BUSY
);
3388 /* Not discarding: clean up and prepare for reuse */
3390 bp
->b_datap
= (uintptr_t)NULL
;
3391 bp
->b_upl
= (void *)NULL
;
3393 * preserve the state of whether this buffer
3394 * was allocated on the fly or not...
3395 * the only other flag that should be set at
3396 * this point is BL_BUSY...
3399 bp
->b_owner
= current_thread();
3402 bp
->b_lflags
= BL_BUSY
;
3403 bp
->b_flags
= (bp
->b_flags
& B_HDRALLOC
);
3405 bp
->b_blkno
= bp
->b_lblkno
= 0;
3406 bp
->b_iodone
= NULL
;
3410 bp
->b_dirtyoff
= bp
->b_dirtyend
= 0;
3411 bp
->b_validoff
= bp
->b_validend
= 0;
3412 #ifdef CONFIG_PROTECT
3415 bzero(&bp
->b_attr
, sizeof(struct bufattr
));
3417 lck_mtx_lock_spin(buf_mtxp
);
3425 buf_invalblkno(vnode_t vp
, daddr64_t lblkno
, int flags
)
3429 struct bufhashhdr
*dp
;
3431 dp
= BUFHASH(vp
, lblkno
);
3434 lck_mtx_lock_spin(buf_mtxp
);
3436 if ((bp
= incore_locked(vp
, lblkno
, dp
)) == (struct buf
*)0) {
3437 lck_mtx_unlock(buf_mtxp
);
3440 if (ISSET(bp
->b_lflags
, BL_BUSY
)) {
3441 if ( !ISSET(flags
, BUF_WAIT
)) {
3442 lck_mtx_unlock(buf_mtxp
);
3445 SET(bp
->b_lflags
, BL_WANTED
);
3447 error
= msleep((caddr_t
)bp
, buf_mtxp
, PDROP
| (PRIBIO
+ 1), "buf_invalblkno", NULL
);
3454 bremfree_locked(bp
);
3455 SET(bp
->b_lflags
, BL_BUSY
);
3456 SET(bp
->b_flags
, B_INVAL
);
3459 bp
->b_owner
= current_thread();
3462 lck_mtx_unlock(buf_mtxp
);
3472 int need_wakeup
= 0;
3474 lck_mtx_lock_spin(buf_mtxp
);
3476 if (ISSET(bp
->b_lflags
, BL_WANTED
)) {
3478 * delay the actual wakeup until after we
3479 * clear BL_BUSY and we've dropped buf_mtxp
3484 bp
->b_owner
= current_thread();
3488 * Unlock the buffer.
3490 CLR(bp
->b_lflags
, (BL_BUSY
| BL_WANTED
));
3493 lck_mtx_unlock(buf_mtxp
);
3497 * Wake up any proceeses waiting for _this_ buffer to become free.
3505 buf_acquire(buf_t bp
, int flags
, int slpflag
, int slptimeo
) {
3508 lck_mtx_lock_spin(buf_mtxp
);
3510 error
= buf_acquire_locked(bp
, flags
, slpflag
, slptimeo
);
3512 lck_mtx_unlock(buf_mtxp
);
3519 buf_acquire_locked(buf_t bp
, int flags
, int slpflag
, int slptimeo
)
3524 if (ISSET(bp
->b_flags
, B_LOCKED
)) {
3525 if ((flags
& BAC_SKIP_LOCKED
))
3528 if ((flags
& BAC_SKIP_NONLOCKED
))
3531 if (ISSET(bp
->b_lflags
, BL_BUSY
)) {
3533 * since the lck_mtx_lock may block, the buffer
3534 * may become BUSY, so we need to
3535 * recheck for a NOWAIT request
3537 if (flags
& BAC_NOWAIT
)
3539 SET(bp
->b_lflags
, BL_WANTED
);
3541 /* the hz value is 100; which leads to 10ms */
3542 ts
.tv_sec
= (slptimeo
/100);
3543 ts
.tv_nsec
= (slptimeo
% 100) * 10 * NSEC_PER_USEC
* 1000;
3544 error
= msleep((caddr_t
)bp
, buf_mtxp
, slpflag
| (PRIBIO
+ 1), "buf_acquire", &ts
);
3550 if (flags
& BAC_REMOVE
)
3551 bremfree_locked(bp
);
3552 SET(bp
->b_lflags
, BL_BUSY
);
3556 bp
->b_owner
= current_thread();
3564 * Wait for operations on the buffer to complete.
3565 * When they do, extract and return the I/O's error value.
3568 buf_biowait(buf_t bp
)
3570 while (!ISSET(bp
->b_flags
, B_DONE
)) {
3572 lck_mtx_lock_spin(buf_mtxp
);
3574 if (!ISSET(bp
->b_flags
, B_DONE
)) {
3575 DTRACE_IO1(wait__start
, buf_t
, bp
);
3576 (void) msleep(bp
, buf_mtxp
, PDROP
| (PRIBIO
+1), "buf_biowait", NULL
);
3577 DTRACE_IO1(wait__done
, buf_t
, bp
);
3579 lck_mtx_unlock(buf_mtxp
);
3581 /* check for interruption of I/O (e.g. via NFS), then errors. */
3582 if (ISSET(bp
->b_flags
, B_EINTR
)) {
3583 CLR(bp
->b_flags
, B_EINTR
);
3585 } else if (ISSET(bp
->b_flags
, B_ERROR
))
3586 return (bp
->b_error
? bp
->b_error
: EIO
);
3593 * Mark I/O complete on a buffer.
3595 * If a callback has been requested, e.g. the pageout
3596 * daemon, do so. Otherwise, awaken waiting processes.
3598 * [ Leffler, et al., says on p.247:
3599 * "This routine wakes up the blocked process, frees the buffer
3600 * for an asynchronous write, or, for a request by the pagedaemon
3601 * process, invokes a procedure specified in the buffer structure" ]
3603 * In real life, the pagedaemon (or other system processes) wants
3604 * to do async stuff to, and doesn't want the buffer buf_brelse()'d.
3605 * (for swap pager, that puts swap buffers on the free lists (!!!),
3606 * for the vn device, that puts malloc'd buffers on the free lists!)
3608 extern struct timeval priority_IO_timestamp_for_root
;
3609 extern int hard_throttle_on_root
;
3612 buf_biodone(buf_t bp
)
3616 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW
, 387)) | DBG_FUNC_START
,
3617 bp
, bp
->b_datap
, bp
->b_flags
, 0, 0);
3619 if (ISSET(bp
->b_flags
, B_DONE
))
3620 panic("biodone already");
3622 if (ISSET(bp
->b_flags
, B_ERROR
)) {
3626 if (bp
->b_vp
&& bp
->b_vp
->v_mount
) {
3627 mp
= bp
->b_vp
->v_mount
;
3632 if (mp
&& (bp
->b_flags
& B_READ
) == 0) {
3633 update_last_io_time(mp
);
3634 INCR_PENDING_IO(-(pending_io_t
)buf_count(bp
), mp
->mnt_pending_write_size
);
3636 INCR_PENDING_IO(-(pending_io_t
)buf_count(bp
), mp
->mnt_pending_read_size
);
3639 if (kdebug_enable
) {
3640 int code
= DKIO_DONE
;
3642 if (bp
->b_flags
& B_READ
)
3644 if (bp
->b_flags
& B_ASYNC
)
3647 if (bp
->b_flags
& B_META
)
3649 else if (bp
->b_flags
& B_PAGEIO
)
3650 code
|= DKIO_PAGING
;
3652 if (bp
->b_flags
& B_THROTTLED_IO
)
3653 code
|= DKIO_THROTTLE
;
3654 else if (bp
->b_flags
& B_PASSIVE
)
3655 code
|= DKIO_PASSIVE
;
3657 KERNEL_DEBUG_CONSTANT(FSDBG_CODE(DBG_DKRW
, code
) | DBG_FUNC_NONE
,
3658 bp
, (uintptr_t)bp
->b_vp
,
3659 bp
->b_resid
, bp
->b_error
, 0);
3661 if ((bp
->b_vp
!= NULLVP
) &&
3662 ((bp
->b_flags
& (B_IOSTREAMING
| B_PAGEIO
| B_READ
)) == (B_PAGEIO
| B_READ
)) &&
3663 (bp
->b_vp
->v_mount
->mnt_kern_flag
& MNTK_ROOTDEV
)) {
3664 microuptime(&priority_IO_timestamp_for_root
);
3665 hard_throttle_on_root
= 0;
3669 * I/O was done, so don't believe
3670 * the DIRTY state from VM anymore...
3671 * and we need to reset the THROTTLED/PASSIVE
3674 CLR(bp
->b_flags
, (B_WASDIRTY
| B_THROTTLED_IO
| B_PASSIVE
));
3675 CLR(bp
->b_attr
.ba_flags
, (BA_THROTTLED_IO
));
3676 DTRACE_IO1(done
, buf_t
, bp
);
3678 if (!ISSET(bp
->b_flags
, B_READ
) && !ISSET(bp
->b_flags
, B_RAW
))
3680 * wake up any writer's blocked
3681 * on throttle or waiting for I/O
3684 vnode_writedone(bp
->b_vp
);
3686 if (ISSET(bp
->b_flags
, (B_CALL
| B_FILTER
))) { /* if necessary, call out */
3687 void (*iodone_func
)(struct buf
*, void *) = bp
->b_iodone
;
3688 void *arg
= bp
->b_transaction
;
3689 int callout
= ISSET(bp
->b_flags
, B_CALL
);
3691 if (iodone_func
== NULL
)
3692 panic("biodone: bp @ %p has NULL b_iodone!\n", bp
);
3694 CLR(bp
->b_flags
, (B_CALL
| B_FILTER
)); /* filters and callouts are one-shot */
3695 bp
->b_iodone
= NULL
;
3696 bp
->b_transaction
= NULL
;
3699 SET(bp
->b_flags
, B_DONE
); /* note that it's done */
3701 (*iodone_func
)(bp
, arg
);
3705 * assumes that the callback function takes
3706 * ownership of the bp and deals with releasing it if necessary
3711 * in this case the call back function is acting
3712 * strictly as a filter... it does not take
3713 * ownership of the bp and is expecting us
3714 * to finish cleaning up... this is currently used
3715 * by the HFS journaling code
3718 if (ISSET(bp
->b_flags
, B_ASYNC
)) { /* if async, release it */
3719 SET(bp
->b_flags
, B_DONE
); /* note that it's done */
3722 } else { /* or just wakeup the buffer */
3724 * by taking the mutex, we serialize
3725 * the buf owner calling buf_biowait so that we'll
3726 * only see him in one of 2 states...
3727 * state 1: B_DONE wasn't set and he's
3729 * state 2: he's blocked trying to take the
3730 * mutex before looking at B_DONE
3731 * BL_WANTED is cleared in case anyone else
3732 * is blocked waiting for the buffer... note
3733 * that we haven't cleared B_BUSY yet, so if
3734 * they do get to run, their going to re-set
3735 * BL_WANTED and go back to sleep
3737 lck_mtx_lock_spin(buf_mtxp
);
3739 CLR(bp
->b_lflags
, BL_WANTED
);
3740 SET(bp
->b_flags
, B_DONE
); /* note that it's done */
3742 lck_mtx_unlock(buf_mtxp
);
3747 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW
, 387)) | DBG_FUNC_END
,
3748 (uintptr_t)bp
, (uintptr_t)bp
->b_datap
, bp
->b_flags
, 0, 0);
3752 * Return a count of buffers on the "locked" queue.
3755 count_lock_queue(void)
3760 lck_mtx_lock_spin(buf_mtxp
);
3762 for (bp
= bufqueues
[BQ_LOCKED
].tqh_first
; bp
;
3763 bp
= bp
->b_freelist
.tqe_next
)
3765 lck_mtx_unlock(buf_mtxp
);
3771 * Return a count of 'busy' buffers. Used at the time of shutdown.
3774 count_busy_buffers(void)
3776 return buf_busycount
+ bufstats
.bufs_iobufinuse
;
3781 * Print out statistics on the current allocation of the buffer pool.
3782 * Can be enabled to print out on every ``sync'' by setting "syncprt"
3783 * in vfs_syscalls.c using sysctl.
3791 int counts
[MAXBSIZE
/CLBYTES
+1];
3792 static char *bname
[BQUEUES
] =
3793 { "LOCKED", "LRU", "AGE", "EMPTY", "META", "LAUNDRY" };
3795 for (dp
= bufqueues
, i
= 0; dp
< &bufqueues
[BQUEUES
]; dp
++, i
++) {
3797 for (j
= 0; j
<= MAXBSIZE
/CLBYTES
; j
++)
3800 lck_mtx_lock(buf_mtxp
);
3802 for (bp
= dp
->tqh_first
; bp
; bp
= bp
->b_freelist
.tqe_next
) {
3803 counts
[bp
->b_bufsize
/CLBYTES
]++;
3806 lck_mtx_unlock(buf_mtxp
);
3808 printf("%s: total-%d", bname
[i
], count
);
3809 for (j
= 0; j
<= MAXBSIZE
/CLBYTES
; j
++)
3811 printf(", %d-%d", j
* CLBYTES
, counts
[j
]);
3815 #endif /* DIAGNOSTIC */
3817 #define NRESERVEDIOBUFS 128
3821 alloc_io_buf(vnode_t vp
, int priv
)
3825 lck_mtx_lock_spin(iobuffer_mtxp
);
3827 while (((niobuf_headers
- NRESERVEDIOBUFS
< bufstats
.bufs_iobufinuse
) && !priv
) ||
3828 (bp
= iobufqueue
.tqh_first
) == NULL
) {
3829 bufstats
.bufs_iobufsleeps
++;
3832 (void) msleep(&need_iobuffer
, iobuffer_mtxp
, PSPIN
| (PRIBIO
+1), (const char *)"alloc_io_buf", NULL
);
3834 TAILQ_REMOVE(&iobufqueue
, bp
, b_freelist
);
3836 bufstats
.bufs_iobufinuse
++;
3837 if (bufstats
.bufs_iobufinuse
> bufstats
.bufs_iobufmax
)
3838 bufstats
.bufs_iobufmax
= bufstats
.bufs_iobufinuse
;
3840 lck_mtx_unlock(iobuffer_mtxp
);
3843 * initialize various fields
3844 * we don't need to hold the mutex since the buffer
3845 * is now private... the vp should have a reference
3846 * on it and is not protected by this mutex in any event
3848 bp
->b_timestamp
= 0;
3853 bp
->b_lflags
= BL_BUSY
| BL_IOBUF
;
3854 bp
->b_redundancy_flags
= 0;
3855 bp
->b_blkno
= bp
->b_lblkno
= 0;
3857 bp
->b_owner
= current_thread();
3860 bp
->b_iodone
= NULL
;
3867 #ifdef CONFIG_PROTECT
3870 bzero(&bp
->b_attr
, sizeof(struct bufattr
));
3872 if (vp
&& (vp
->v_type
== VBLK
|| vp
->v_type
== VCHR
))
3873 bp
->b_dev
= vp
->v_rdev
;
3882 free_io_buf(buf_t bp
)
3884 int need_wakeup
= 0;
3887 * put buffer back on the head of the iobufqueue
3890 bp
->b_flags
= B_INVAL
;
3892 lck_mtx_lock_spin(iobuffer_mtxp
);
3894 binsheadfree(bp
, &iobufqueue
, -1);
3896 if (need_iobuffer
) {
3898 * Wake up any processes waiting because they need an io buffer
3900 * do the wakeup after we drop the mutex... it's possible that the
3901 * wakeup will be superfluous if need_iobuffer gets set again and
3902 * another thread runs this path, but it's highly unlikely, doesn't
3903 * hurt, and it means we don't hold up I/O progress if the wakeup blocks
3904 * trying to grab a task related lock...
3909 if (bufstats
.bufs_iobufinuse
<= 0)
3910 panic("free_io_buf: bp(%p) - bufstats.bufs_iobufinuse < 0", bp
);
3912 bufstats
.bufs_iobufinuse
--;
3914 lck_mtx_unlock(iobuffer_mtxp
);
3917 wakeup(&need_iobuffer
);
3924 lck_mtx_lock_spin(buf_mtxp
);
3928 buf_list_unlock(void)
3930 lck_mtx_unlock(buf_mtxp
);
3934 * If getnewbuf() calls bcleanbuf() on the same thread
3935 * there is a potential for stack overrun and deadlocks.
3936 * So we always handoff the work to a worker thread for completion
3941 bcleanbuf_thread_init(void)
3943 thread_t thread
= THREAD_NULL
;
3945 /* create worker thread */
3946 kernel_thread_start((thread_continue_t
)bcleanbuf_thread
, NULL
, &thread
);
3947 thread_deallocate(thread
);
3950 typedef int (*bcleanbufcontinuation
)(int);
3953 bcleanbuf_thread(void)
3960 lck_mtx_lock_spin(buf_mtxp
);
3962 while ( (bp
= TAILQ_FIRST(&bufqueues
[BQ_LAUNDRY
])) == NULL
) {
3963 (void)msleep0(&bufqueues
[BQ_LAUNDRY
], buf_mtxp
, PRIBIO
|PDROP
, "blaundry", 0, (bcleanbufcontinuation
)bcleanbuf_thread
);
3967 * Remove from the queue
3969 bremfree_locked(bp
);
3972 * Buffer is no longer on any free list
3974 SET(bp
->b_lflags
, BL_BUSY
);
3978 bp
->b_owner
= current_thread();
3982 lck_mtx_unlock(buf_mtxp
);
3986 error
= bawrite_internal(bp
, 0);
3989 bp
->b_whichq
= BQ_LAUNDRY
;
3990 bp
->b_timestamp
= buf_timestamp();
3992 lck_mtx_lock_spin(buf_mtxp
);
3994 binstailfree(bp
, &bufqueues
[BQ_LAUNDRY
], BQ_LAUNDRY
);
3997 /* we never leave a busy page on the laundry queue */
3998 CLR(bp
->b_lflags
, BL_BUSY
);
4001 bp
->b_owner
= current_thread();
4005 lck_mtx_unlock(buf_mtxp
);
4007 if (loopcnt
> MAXLAUNDRY
) {
4009 * bawrite_internal() can return errors if we're throttled. If we've
4010 * done several I/Os and failed, give the system some time to unthrottle
4013 (void)tsleep((void *)&bufqueues
[BQ_LAUNDRY
], PRIBIO
, "blaundry", 1);
4016 /* give other threads a chance to run */
4017 (void)thread_block(THREAD_CONTINUE_NULL
);
4026 brecover_data(buf_t bp
)
4030 upl_page_info_t
*pl
;
4032 vnode_t vp
= bp
->b_vp
;
4036 if ( !UBCINFOEXISTS(vp
) || bp
->b_bufsize
== 0)
4039 upl_flags
= UPL_PRECIOUS
;
4040 if (! (buf_flags(bp
) & B_READ
)) {
4042 * "write" operation: let the UPL subsystem know
4043 * that we intend to modify the buffer cache pages we're
4046 upl_flags
|= UPL_WILL_MODIFY
;
4049 kret
= ubc_create_upl(vp
,
4050 ubc_blktooff(vp
, bp
->b_lblkno
),
4055 if (kret
!= KERN_SUCCESS
)
4056 panic("Failed to create UPL");
4058 for (upl_offset
= 0; upl_offset
< bp
->b_bufsize
; upl_offset
+= PAGE_SIZE
) {
4060 if (!upl_valid_page(pl
, upl_offset
/ PAGE_SIZE
) || !upl_dirty_page(pl
, upl_offset
/ PAGE_SIZE
)) {
4061 ubc_upl_abort(upl
, 0);
4067 kret
= ubc_upl_map(upl
, (vm_offset_t
*)&(bp
->b_datap
));
4069 if (kret
!= KERN_SUCCESS
)
4070 panic("getblk: ubc_upl_map() failed with (%d)", kret
);
4075 SET(bp
->b_flags
, B_INVAL
);
4082 buffer_cache_gc(int all
)
4085 boolean_t did_large_zfree
= FALSE
;
4086 boolean_t need_wakeup
= FALSE
;
4087 int now
= buf_timestamp();
4088 uint32_t found
= 0, total_found
= 0;
4089 struct bqueues privq
;
4090 int thresh_hold
= BUF_STALE_THRESHHOLD
;
4095 * We only care about metadata (incore storage comes from zalloc()).
4096 * No more than 1024 buffers total, and only those not accessed within the
4097 * last 30s. We will also only examine 128 buffers during a single grab
4098 * of the lock in order to limit lock hold time.
4100 lck_mtx_lock(buf_mtxp
);
4104 need_wakeup
= FALSE
;
4106 while (((bp
= TAILQ_FIRST(&bufqueues
[BQ_META
]))) &&
4107 (now
> bp
->b_timestamp
) &&
4108 (now
- bp
->b_timestamp
> thresh_hold
) &&
4109 (found
< BUF_MAX_GC_BATCH_SIZE
)) {
4111 /* Remove from free list */
4112 bremfree_locked(bp
);
4116 bp
->b_owner
= current_thread();
4120 /* If dirty, move to laundry queue and remember to do wakeup */
4121 if (ISSET(bp
->b_flags
, B_DELWRI
)) {
4122 SET(bp
->b_lflags
, BL_WANTDEALLOC
);
4131 * Mark busy and put on private list. We could technically get
4132 * away without setting BL_BUSY here.
4134 SET(bp
->b_lflags
, BL_BUSY
);
4138 * Remove from hash and dissociate from vp.
4145 TAILQ_INSERT_TAIL(&privq
, bp
, b_freelist
);
4152 /* Drop lock for batch processing */
4153 lck_mtx_unlock(buf_mtxp
);
4155 /* Wakeup and yield for laundry if need be */
4157 wakeup(&bufqueues
[BQ_LAUNDRY
]);
4158 (void)thread_block(THREAD_CONTINUE_NULL
);
4161 /* Clean up every buffer on private list */
4162 TAILQ_FOREACH(bp
, &privq
, b_freelist
) {
4163 /* Take note if we've definitely freed at least a page to a zone */
4164 if ((ISSET(bp
->b_flags
, B_ZALLOC
)) && (buf_size(bp
) >= PAGE_SIZE
)) {
4165 did_large_zfree
= TRUE
;
4168 trace(TR_BRELSE
, pack(bp
->b_vp
, bp
->b_bufsize
), bp
->b_lblkno
);
4171 buf_free_meta_store(bp
);
4173 /* Release credentials */
4174 buf_release_credentials(bp
);
4176 /* Prepare for moving to empty queue */
4177 CLR(bp
->b_flags
, (B_META
| B_ZALLOC
| B_DELWRI
| B_LOCKED
4178 | B_AGE
| B_ASYNC
| B_NOCACHE
| B_FUA
));
4179 bp
->b_whichq
= BQ_EMPTY
;
4183 lck_mtx_lock(buf_mtxp
);
4185 /* Back under lock, move them all to invalid hash and clear busy */
4186 TAILQ_FOREACH(bp
, &privq
, b_freelist
) {
4187 binshash(bp
, &invalhash
);
4188 CLR(bp
->b_lflags
, BL_BUSY
);
4192 if (bp
->b_owner
!= current_thread()) {
4193 panic("Buffer stolen from buffer_cache_gc()");
4195 bp
->b_owner
= current_thread();
4200 /* And do a big bulk move to the empty queue */
4201 TAILQ_CONCAT(&bufqueues
[BQ_EMPTY
], &privq
, b_freelist
);
4202 total_found
+= found
;
4204 } while ((all
|| (total_found
< BUF_MAX_GC_COUNT
)) && (found
== BUF_MAX_GC_BATCH_SIZE
));
4206 lck_mtx_unlock(buf_mtxp
);
4208 return did_large_zfree
;
4221 bp_cmp(void *a
, void *b
)
4223 buf_t
*bp_a
= *(buf_t
**)a
,
4224 *bp_b
= *(buf_t
**)b
;
4227 // don't have to worry about negative block
4228 // numbers so this is ok to do.
4230 res
= (bp_a
->b_blkno
- bp_b
->b_blkno
);
4237 bflushq(int whichq
, mount_t mp
)
4241 int total_writes
= 0;
4242 static buf_t flush_table
[NFLUSH
];
4244 if (whichq
< 0 || whichq
>= BQUEUES
) {
4249 lck_mtx_lock(buf_mtxp
);
4251 bp
= TAILQ_FIRST(&bufqueues
[whichq
]);
4253 for (buf_count
= 0; bp
; bp
= next
) {
4254 next
= bp
->b_freelist
.tqe_next
;
4256 if (bp
->b_vp
== NULL
|| bp
->b_vp
->v_mount
!= mp
) {
4260 if (ISSET(bp
->b_flags
, B_DELWRI
) && !ISSET(bp
->b_lflags
, BL_BUSY
)) {
4262 bremfree_locked(bp
);
4264 bp
->b_owner
= current_thread();
4267 SET(bp
->b_lflags
, BL_BUSY
);
4270 flush_table
[buf_count
] = bp
;
4274 if (buf_count
>= NFLUSH
) {
4275 lck_mtx_unlock(buf_mtxp
);
4277 qsort(flush_table
, buf_count
, sizeof(struct buf
*), bp_cmp
);
4279 for (i
= 0; i
< buf_count
; i
++) {
4280 buf_bawrite(flush_table
[i
]);
4286 lck_mtx_unlock(buf_mtxp
);
4288 if (buf_count
> 0) {
4289 qsort(flush_table
, buf_count
, sizeof(struct buf
*), bp_cmp
);
4291 for (i
= 0; i
< buf_count
; i
++) {
4292 buf_bawrite(flush_table
[i
]);
4296 return (total_writes
);
4303 /* XXX move this to a separate file */
4306 * NOTE: THIS CODE HAS NOT BEEN UPDATED
4307 * WITH RESPECT TO THE NEW LOCKING MODEL
4312 * Dynamic Scaling of the Buffer Queues
4315 typedef long long blsize_t
;
4317 blsize_t MAXNBUF
; /* initialize to (sane_size / PAGE_SIZE) */
4318 /* Global tunable limits */
4319 blsize_t nbufh
; /* number of buffer headers */
4320 blsize_t nbuflow
; /* minimum number of buffer headers required */
4321 blsize_t nbufhigh
; /* maximum number of buffer headers allowed */
4322 blsize_t nbuftarget
; /* preferred number of buffer headers */
4327 * 1. 0 < nbuflow <= nbufh <= nbufhigh
4328 * 2. nbufhigh <= MAXNBUF
4329 * 3. 0 < nbuflow <= nbuftarget <= nbufhigh
4330 * 4. nbufh can not be set by sysctl().
4333 /* Per queue tunable limits */
4336 blsize_t bl_nlow
; /* minimum number of buffer headers required */
4337 blsize_t bl_num
; /* number of buffer headers on the queue */
4338 blsize_t bl_nlhigh
; /* maximum number of buffer headers allowed */
4339 blsize_t bl_target
; /* preferred number of buffer headers */
4340 long bl_stale
; /* Seconds after which a buffer is considered stale */
4346 * 1. 0 <= bl_nlow <= bl_num <= bl_nlhigh
4347 * 2. bl_nlhigh <= MAXNBUF
4348 * 3. bufqlim[BQ_META].bl_nlow != 0
4349 * 4. bufqlim[BQ_META].bl_nlow > (number of possible concurrent
4350 * file system IO operations)
4351 * 5. bl_num can not be set by sysctl().
4352 * 6. bl_nhigh <= nbufhigh
4358 * Defining it blsize_t as long permits 2^31 buffer headers per queue.
4359 * Which can describe (2^31 * PAGE_SIZE) memory per queue.
4361 * These limits are exported to by means of sysctl().
4362 * It was decided to define blsize_t as a 64 bit quantity.
4363 * This will make sure that we will not be required to change it
4364 * as long as we do not exceed 64 bit address space for the kernel.
4366 * low and high numbers parameters initialized at compile time
4367 * and boot arguments can be used to override them. sysctl()
4368 * would not change the value. sysctl() can get all the values
4369 * but can set only target. num is the current level.
4371 * Advantages of having a "bufqscan" thread doing the balancing are,
4372 * Keep enough bufs on BQ_EMPTY.
4373 * getnewbuf() by default will always select a buffer from the BQ_EMPTY.
4374 * getnewbuf() perfoms best if a buffer was found there.
4375 * Also this minimizes the possibility of starting IO
4376 * from getnewbuf(). That's a performance win, too.
4378 * Localize complex logic [balancing as well as time aging]
4381 * Simplify getnewbuf() logic by elimination of time aging code.
4387 * The goal of the dynamic scaling of the buffer queues to to keep
4388 * the size of the LRU close to bl_target. Buffers on a queue would
4391 * There would be a thread which will be responsible for "balancing"
4392 * the buffer cache queues.
4394 * The scan order would be: AGE, LRU, META, EMPTY.
4397 long bufqscanwait
= 0;
4399 static void bufqscan_thread();
4400 static int balancebufq(int q
);
4401 static int btrimempty(int n
);
4402 static __inline__
int initbufqscan(void);
4403 static __inline__
int nextbufq(int q
);
4404 static void buqlimprt(int all
);
4407 static __inline__
void
4410 if ((q
< 0) || (q
>= BQUEUES
))
4413 bufqlim
[q
].bl_num
++;
4417 static __inline__
void
4420 if ((q
< 0) || (q
>= BQUEUES
))
4423 bufqlim
[q
].bl_num
--;
4428 bufq_balance_thread_init(void)
4430 thread_t thread
= THREAD_NULL
;
4432 if (bufqscanwait
++ == 0) {
4434 /* Initalize globals */
4435 MAXNBUF
= (sane_size
/ PAGE_SIZE
);
4436 nbufh
= nbuf_headers
;
4437 nbuflow
= min(nbufh
, 100);
4438 nbufhigh
= min(MAXNBUF
, max(nbufh
, 2048));
4439 nbuftarget
= (sane_size
>> 5) / PAGE_SIZE
;
4440 nbuftarget
= max(nbuflow
, nbuftarget
);
4441 nbuftarget
= min(nbufhigh
, nbuftarget
);
4444 * Initialize the bufqlim
4448 bufqlim
[BQ_LOCKED
].bl_nlow
= 0;
4449 bufqlim
[BQ_LOCKED
].bl_nlhigh
= 32;
4450 bufqlim
[BQ_LOCKED
].bl_target
= 0;
4451 bufqlim
[BQ_LOCKED
].bl_stale
= 30;
4454 bufqlim
[BQ_LRU
].bl_nlow
= 0;
4455 bufqlim
[BQ_LRU
].bl_nlhigh
= nbufhigh
/4;
4456 bufqlim
[BQ_LRU
].bl_target
= nbuftarget
/4;
4457 bufqlim
[BQ_LRU
].bl_stale
= LRU_IS_STALE
;
4460 bufqlim
[BQ_AGE
].bl_nlow
= 0;
4461 bufqlim
[BQ_AGE
].bl_nlhigh
= nbufhigh
/4;
4462 bufqlim
[BQ_AGE
].bl_target
= nbuftarget
/4;
4463 bufqlim
[BQ_AGE
].bl_stale
= AGE_IS_STALE
;
4466 bufqlim
[BQ_EMPTY
].bl_nlow
= 0;
4467 bufqlim
[BQ_EMPTY
].bl_nlhigh
= nbufhigh
/4;
4468 bufqlim
[BQ_EMPTY
].bl_target
= nbuftarget
/4;
4469 bufqlim
[BQ_EMPTY
].bl_stale
= 600000;
4472 bufqlim
[BQ_META
].bl_nlow
= 0;
4473 bufqlim
[BQ_META
].bl_nlhigh
= nbufhigh
/4;
4474 bufqlim
[BQ_META
].bl_target
= nbuftarget
/4;
4475 bufqlim
[BQ_META
].bl_stale
= META_IS_STALE
;
4478 bufqlim
[BQ_LOCKED
].bl_nlow
= 0;
4479 bufqlim
[BQ_LOCKED
].bl_nlhigh
= 32;
4480 bufqlim
[BQ_LOCKED
].bl_target
= 0;
4481 bufqlim
[BQ_LOCKED
].bl_stale
= 30;
4486 /* create worker thread */
4487 kernel_thread_start((thread_continue_t
)bufqscan_thread
, NULL
, &thread
);
4488 thread_deallocate(thread
);
4491 /* The workloop for the buffer balancing thread */
4499 int q
; /* buffer queue to process */
4503 moretodo
|= balancebufq(q
);
4512 (void)tsleep((void *)&bufqscanwait
, PRIBIO
, "bufqscanwait", 60 * hz
);
4517 /* Seed for the buffer queue balancing */
4518 static __inline__
int
4521 /* Start with AGE queue */
4525 /* Pick next buffer queue to balance */
4526 static __inline__
int
4529 int order
[] = { BQ_AGE
, BQ_LRU
, BQ_META
, BQ_EMPTY
, 0 };
4536 /* function to balance the buffer queues */
4543 /* reject invalid q */
4544 if ((q
< 0) || (q
>= BQUEUES
))
4547 /* LOCKED or LAUNDRY queue MUST not be balanced */
4548 if ((q
== BQ_LOCKED
) || (q
== BQ_LAUNDRY
))
4551 n
= (bufqlim
[q
].bl_num
- bufqlim
[q
].bl_target
);
4553 /* If queue has less than target nothing more to do */
4558 /* Balance only a small amount (12.5%) at a time */
4562 /* EMPTY queue needs special handling */
4563 if (q
== BQ_EMPTY
) {
4564 moretodo
|= btrimempty(n
);
4568 t
= buf_timestamp():
4570 for (; n
> 0; n
--) {
4571 struct buf
*bp
= bufqueues
[q
].tqh_first
;
4575 /* check if it's stale */
4576 if ((t
- bp
->b_timestamp
) > bufqlim
[q
].bl_stale
) {
4577 if (bcleanbuf(bp
, FALSE
)) {
4578 /* buf_bawrite() issued, bp not ready */
4581 /* release the cleaned buffer to BQ_EMPTY */
4582 SET(bp
->b_flags
, B_INVAL
);
4597 * When struct buf are allocated dynamically, this would
4598 * reclaim upto 'n' struct buf from the empty queue.
4608 static char *bname
[BQUEUES
] =
4609 { "LOCKED", "LRU", "AGE", "EMPTY", "META", "LAUNDRY" };
4612 for (i
= 0; i
< BQUEUES
; i
++) {
4613 printf("%s : ", bname
[i
]);
4614 printf("min = %ld, ", (long)bufqlim
[i
].bl_nlow
);
4615 printf("cur = %ld, ", (long)bufqlim
[i
].bl_num
);
4616 printf("max = %ld, ", (long)bufqlim
[i
].bl_nlhigh
);
4617 printf("target = %ld, ", (long)bufqlim
[i
].bl_target
);
4618 printf("stale after %ld seconds\n", bufqlim
[i
].bl_stale
);
4621 for (i
= 0; i
< BQUEUES
; i
++) {
4622 printf("%s : ", bname
[i
]);
4623 printf("cur = %ld, ", (long)bufqlim
[i
].bl_num
);