Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F107175907
D20579.id58876.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D20579.id58876.diff
View Options
Index: kern/subr_blist.c
===================================================================
--- kern/subr_blist.c
+++ kern/subr_blist.c
@@ -121,6 +121,7 @@
#define malloc(a,b,c) calloc(a, 1)
#define free(a,b) free(a)
#define ummin(a,b) ((a) < (b) ? (a) : (b))
+#define imin(a,b) ((a) < (b) ? (a) : (b))
#define KASSERT(a,b) assert(a)
#include <sys/blist.h>
@@ -300,8 +301,8 @@
KASSERT(*count <= maxcount,
("invalid parameters %d > %d", *count, maxcount));
- KASSERT(maxcount <= BLIST_MAX_ALLOC,
- ("allocation too large: %d", maxcount));
+ KASSERT(*count <= BLIST_MAX_ALLOC,
+ ("minimum allocation too large: %d", *count));
/*
* This loop iterates at most twice. An allocation failure in the
@@ -606,58 +607,71 @@
*/
/*
- * BLST_NEXT_LEAF_ALLOC() - allocate the first few blocks in the next leaf.
+ * BLST_NEXT_LEAF_ALLOC() - allocate the blocks starting with the next leaf.
*
- * 'scan' is a leaf node, associated with a block containing 'blk'.
- * The next leaf node could be adjacent, or several nodes away if the
- * least common ancestor of 'scan' and its neighbor is several levels
- * up. Use 'blk' to determine how many meta-nodes lie between the
- * leaves. If the next leaf has enough initial bits set, clear them
- * and clear the bits in the meta nodes on the path up to the least
- * common ancestor to mark any subtrees made completely empty.
+ * 'scan' is a leaf node, and its first block is at address 'start'. The
+ * next leaf node could be adjacent, or several nodes away if the least
+ * common ancestor of 'scan' and its neighbor is several levels up. Use
+ * addresses to determine how many meta-nodes lie between the leaves. If
+ * sequence of leaves starting with the next one has enough initial bits
+ * set, clear them and clear the bits in the meta nodes on the path up to
+ * the least common ancestor to mark any subtrees made completely empty.
*/
static int
-blst_next_leaf_alloc(blmeta_t *scan, daddr_t blk, int count, int maxcount)
+blst_next_leaf_alloc(blmeta_t *scan, daddr_t start, int count, int maxcount)
{
- blmeta_t *next;
u_daddr_t radix;
+ daddr_t blk;
int avail, digit;
- next = scan + 1;
- blk += BLIST_BMAP_RADIX;
- radix = BLIST_BMAP_RADIX;
- while ((next->bm_bitmap & 1) == 1 &&
- (digit = ((blk / radix) & BLIST_META_MASK)) == 0) {
- next++;
- radix *= BLIST_META_RADIX;
+ start += BLIST_BMAP_RADIX;
+ for (blk = start; blk - start < maxcount; blk += BLIST_BMAP_RADIX) {
+ /* Skip meta-nodes, as long as they promise more free blocks. */
+ radix = BLIST_BMAP_RADIX;
+ while (((++scan)->bm_bitmap & 1) == 1 &&
+ ((blk / radix) & BLIST_META_MASK) == 0)
+ radix *= BLIST_META_RADIX;
+ if (~scan->bm_bitmap != 0) {
+ /*
+ * Either there is no next leaf with any free blocks,
+ * or we've reached the next leaf and found that some
+ * of its blocks are not free. In the first case,
+ * bitpos() returns zero here.
+ */
+ avail = blk - start + bitpos(~scan->bm_bitmap);
+ if (avail < count) {
+ /*
+ * There isn't a next leaf with enough free
+ * blocks at its beginning to complete the
+ * spanning allocation.
+ */
+ return (avail);
+ }
+ maxcount = imin(avail, maxcount);
+ }
}
- if ((next->bm_bitmap & 1) != 1)
- return (0);
- avail = (~next->bm_bitmap != 0) ?
- bitpos(~next->bm_bitmap) : BLIST_BMAP_RADIX;
- if (avail < count) {
- /*
- * The next leaf doesn't have enough free blocks at the
- * beginning to complete the spanning allocation.
- */
- return (0);
- }
- count = imin(avail, maxcount);
- /* Clear the first 'count' bits in the next leaf to allocate. */
- next->bm_bitmap &= ~bitrange(0, count);
+
+ scan->bm_bitmap &= ~bitrange(0,
+ 1 + (maxcount + BLIST_BMAP_RADIX - 1) % BLIST_BMAP_RADIX);
- /*
- * Update bitmaps of next-ancestors, up to least common ancestor.
- */
- while (next->bm_bitmap == 0) {
- if (--next == scan) {
+ for (;;) {
+ /* Back up over meta-nodes, clearing bits if necessary. */
+ blk -= BLIST_BMAP_RADIX;
+ radix = BLIST_BMAP_RADIX;
+ while ((digit = ((blk / radix) & BLIST_META_MASK)) == 0) {
+ if ((scan--)->bm_bitmap == 0)
+ scan->bm_bitmap ^= 1;
+ radix *= BLIST_META_RADIX;
+ }
+ if ((scan--)->bm_bitmap == 0)
scan[-digit * radix_to_skip(radix)].bm_bitmap ^=
(u_daddr_t)1 << digit;
+
+ if (blk == start)
break;
- }
- next->bm_bitmap ^= 1;
- }
- return (count);
+ scan->bm_bitmap = 0;
+ }
+ return (maxcount);
}
/*
Index: vm/swap_pager.c
===================================================================
--- vm/swap_pager.c
+++ vm/swap_pager.c
@@ -729,7 +729,8 @@
int mpages, npages;
blk = SWAPBLK_NONE;
- npages = mpages = *io_npages;
+ mpages = *io_npages;
+ npages = imin(BLIST_MAX_ALLOC, mpages);
mtx_lock(&sw_dev_mtx);
sp = swdevhd;
while (!TAILQ_EMPTY(&swtailq)) {
@@ -903,7 +904,7 @@
swp_pager_init_freerange(&s_free, &n_free);
VM_OBJECT_WLOCK(object);
for (i = 0; i < size; i += n) {
- n = min(BLIST_MAX_ALLOC, size - i);
+ n = size - i;
blk = swp_pager_getswapspace(&n, 1);
if (blk == SWAPBLK_NONE) {
swp_pager_meta_free(object, start, i);
@@ -1382,11 +1383,8 @@
struct buf *bp;
daddr_t blk;
- /*
- * Maximum I/O size is limited by a number of factors.
- */
- n = min(BLIST_MAX_ALLOC, count - i);
- n = min(n, nsw_cluster_max);
+ /* Maximum I/O size is limited maximum swap block size. */
+ n = min(count - i, nsw_cluster_max);
/* Get a block of swap of size up to size n. */
blk = swp_pager_getswapspace(&n, 4);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Jan 12, 6:43 AM (19 h, 57 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15762986
Default Alt Text
D20579.id58876.diff (5 KB)
Attached To
Mode
D20579: Remove limit on blist_alloc maxsize, allow bigger getswapspace allocations
Attached
Detach File
Event Timeline
Log In to Comment