Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F131862190
D20001.id56784.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
11 KB
Referenced Files
None
Subscribers
None
D20001.id56784.diff
View Options
Index: sys/kern/subr_blist.c
===================================================================
--- sys/kern/subr_blist.c
+++ sys/kern/subr_blist.c
@@ -130,9 +130,10 @@
/*
* static support functions
*/
-static daddr_t blst_leaf_alloc(blmeta_t *scan, daddr_t blk, int count);
-static daddr_t blst_meta_alloc(blmeta_t *scan, daddr_t cursor, daddr_t count,
- u_daddr_t radix);
+static daddr_t blst_leaf_alloc(blmeta_t *scan, daddr_t blk,
+ int *count, int maxcount);
+static daddr_t blst_meta_alloc(blmeta_t *scan, daddr_t cursor, int *count,
+ int maxcount, u_daddr_t radix);
static void blst_leaf_free(blmeta_t *scan, daddr_t relblk, int count);
static void blst_meta_free(blmeta_t *scan, daddr_t freeBlk, daddr_t count,
u_daddr_t radix);
@@ -193,7 +194,6 @@
/*
* Use binary search, or a faster method, to find the 1 bit in a u_daddr_t.
- * Assumes that the argument has only one bit set.
*/
static inline int
bitpos(u_daddr_t mask)
@@ -206,6 +206,7 @@
return (ffsll(mask) - 1);
#endif
default:
+ mask &= -mask;
lo = 0;
hi = BLIST_BMAP_RADIX;
while (lo + 1 < hi) {
@@ -284,11 +285,13 @@
* not be allocated.
*/
daddr_t
-blist_alloc(blist_t bl, daddr_t count)
+blist_alloc(blist_t bl, int *count, int maxcount)
{
daddr_t blk;
- if (count > BLIST_MAX_ALLOC)
+ if (*count > maxcount)
+ panic("invalid parameters");
+ if (maxcount > BLIST_MAX_ALLOC)
panic("allocation too large");
/*
@@ -299,10 +302,10 @@
*/
for (;;) {
blk = blst_meta_alloc(bl->bl_root, bl->bl_cursor, count,
- bl->bl_radix);
+ maxcount, bl->bl_radix);
if (blk != SWAPBLK_NONE) {
- bl->bl_avail -= count;
- bl->bl_cursor = blk + count;
+ bl->bl_avail -= *count;
+ bl->bl_cursor = blk + *count;
if (bl->bl_cursor == bl->bl_blocks)
bl->bl_cursor = 0;
return (blk);
@@ -649,13 +652,13 @@
* crosses a leaf boundary.
*/
static daddr_t
-blst_leaf_alloc(blmeta_t *scan, daddr_t blk, int count)
+blst_leaf_alloc(blmeta_t *scan, daddr_t blk, int *count, int maxcount)
{
u_daddr_t cursor_mask, mask;
int count1, hi, lo, num_shifts, range1, range_ext;
range1 = 0;
- count1 = count - 1;
+ count1 = *count - 1;
num_shifts = fls(count1);
mask = scan->bm_bitmap;
while ((-mask & ~mask) != 0 && num_shifts > 0) {
@@ -716,7 +719,7 @@
mask &= -mask;
lo = bitpos(mask);
- hi = lo + count;
+ hi = lo + *count;
if (hi > BLIST_BMAP_RADIX) {
/*
* An allocation within this leaf is impossible, so a successful
@@ -759,7 +762,8 @@
* and we have a few optimizations strewn in as well.
*/
static daddr_t
-blst_meta_alloc(blmeta_t *scan, daddr_t cursor, daddr_t count, u_daddr_t radix)
+blst_meta_alloc(blmeta_t *scan, daddr_t cursor, int *count,
+ int maxcount, u_daddr_t radix)
{
daddr_t blk, i, r, skip;
u_daddr_t bit, mask;
@@ -767,7 +771,7 @@
int digit;
if (radix == BLIST_BMAP_RADIX)
- return (blst_leaf_alloc(scan, cursor, count));
+ return (blst_leaf_alloc(scan, cursor, count, maxcount));
blk = cursor & -radix;
scan_from_start = (cursor == blk);
radix /= BLIST_META_RADIX;
@@ -797,12 +801,12 @@
bit = mask & -mask;
digit = bitpos(bit);
i = 1 + digit * skip;
- if (count <= scan[i].bm_bighint) {
+ if (*count <= scan[i].bm_bighint) {
/*
* The allocation might fit beginning in the i'th subtree.
*/
r = blst_meta_alloc(&scan[i], cursor + digit * radix,
- count, radix);
+ count, maxcount, radix);
if (r != SWAPBLK_NONE) {
if (scan[i].bm_bitmap == 0)
scan->bm_bitmap ^= bit;
@@ -818,7 +822,7 @@
*/
if (scan_from_start && !(digit == BLIST_META_RADIX - 1 &&
scan[i].bm_bighint == BLIST_MAX_ALLOC))
- scan->bm_bighint = count - 1;
+ scan->bm_bighint = *count - 1;
return (SWAPBLK_NONE);
}
@@ -1077,7 +1081,7 @@
for (;;) {
char buf[1024];
long long da = 0;
- long long count = 0;
+ int count = 0, maxcount = 0;
printf("%lld/%lld/%lld> ", (long long)blist_avail(bl),
(long long)size, (long long)bl->bl_radix);
@@ -1086,7 +1090,7 @@
break;
switch(buf[0]) {
case 'r':
- if (sscanf(buf + 1, "%lld", &count) == 1) {
+ if (sscanf(buf + 1, "%d", &count) == 1) {
blist_resize(&bl, count, 1, M_WAITOK);
} else {
printf("?\n");
@@ -1102,22 +1106,23 @@
sbuf_delete(s);
break;
case 'a':
- if (sscanf(buf + 1, "%lld", &count) == 1) {
- daddr_t blk = blist_alloc(bl, count);
- printf(" R=%08llx\n", (long long)blk);
+ if (sscanf(buf + 1, "%d%d", &count, &maxcount) == 2) {
+ daddr_t blk = blist_alloc(bl, &count, maxcount);
+ printf(" R=%08llx, c=%08d\n",
+ (long long)blk, count);
} else {
printf("?\n");
}
break;
case 'f':
- if (sscanf(buf + 1, "%llx %lld", &da, &count) == 2) {
+ if (sscanf(buf + 1, "%llx %d", &da, &count) == 2) {
blist_free(bl, da, count);
} else {
printf("?\n");
}
break;
case 'l':
- if (sscanf(buf + 1, "%llx %lld", &da, &count) == 2) {
+ if (sscanf(buf + 1, "%llx %d", &da, &count) == 2) {
printf(" n=%jd\n",
(intmax_t)blist_fill(bl, da, count));
} else {
@@ -1129,17 +1134,22 @@
puts(
"p -print\n"
"s -stats\n"
- "a %d -allocate\n"
+ "a %d %d -allocate\n"
"f %x %d -free\n"
"l %x %d -fill\n"
"r %d -resize\n"
- "h/? -help"
+ "h/? -help\n"
+ "q -quit"
);
break;
+ case 'q':
+ break;
default:
printf("?\n");
break;
}
+ if (buf[0] == 'q')
+ break;
}
return(0);
}
Index: sys/sys/blist.h
===================================================================
--- sys/sys/blist.h
+++ sys/sys/blist.h
@@ -33,7 +33,7 @@
* Usage:
* blist = blist_create(blocks, flags)
* (void) blist_destroy(blist)
- * blkno = blist_alloc(blist, count)
+ * blkno = blist_alloc(blist, &count, maxcount)
* (void) blist_free(blist, blkno, count)
* nblks = blist_fill(blist, blkno, count)
* (void) blist_resize(&blist, count, freeextra, flags)
@@ -69,11 +69,11 @@
#define SWAPBLK_NONE ((daddr_t)((u_daddr_t)SWAPBLK_MASK + 1))/* flag */
/*
- * Both blmeta and bmu_bitmap MUST be a power of 2 in size.
+ * Both blmeta and bm_bitmap MUST be a power of 2 in size.
*/
typedef struct blmeta {
- u_daddr_t bm_bitmap; /* bitmap if we are a leaf */
+ u_daddr_t bm_bitmap; /* bitmap marking unfilled block sets*/
daddr_t bm_bighint; /* biggest contiguous block hint*/
} blmeta_t;
@@ -92,7 +92,7 @@
struct sbuf;
-daddr_t blist_alloc(blist_t blist, daddr_t count);
+daddr_t blist_alloc(blist_t blist, int *count, int maxcount);
daddr_t blist_avail(blist_t blist);
blist_t blist_create(daddr_t blocks, int flags);
void blist_destroy(blist_t blist);
Index: sys/vm/swap_pager.c
===================================================================
--- sys/vm/swap_pager.c
+++ sys/vm/swap_pager.c
@@ -407,7 +407,7 @@
* Swap bitmap functions
*/
static void swp_pager_freeswapspace(daddr_t blk, daddr_t npages);
-static daddr_t swp_pager_getswapspace(int npages);
+static daddr_t swp_pager_getswapspace(int *npages, int limit);
/*
* Metadata functions
@@ -708,9 +708,10 @@
/*
* SWP_PAGER_GETSWAPSPACE() - allocate raw swap space
*
- * Allocate swap for the requested number of pages. The starting
- * swap block number (a page index) is returned or SWAPBLK_NONE
- * if the allocation failed.
+ * Allocate swap for up to the requested number of pages, and at
+ * least a minimum number of pages. The starting swap block number
+ * (a page index) is returned or SWAPBLK_NONE if the allocation
+ * failed.
*
* Also has the side effect of advising that somebody made a mistake
* when they configured swap and didn't configure enough.
@@ -720,38 +721,49 @@
* We allocate in round-robin fashion from the configured devices.
*/
static daddr_t
-swp_pager_getswapspace(int npages)
+swp_pager_getswapspace(int *io_npages, int limit)
{
daddr_t blk;
struct swdevt *sp;
- int i;
+ int mpages, npages;
blk = SWAPBLK_NONE;
+ npages = mpages = *io_npages;
mtx_lock(&sw_dev_mtx);
+ if (TAILQ_EMPTY(&swtailq)) {
+ mtx_unlock(&sw_dev_mtx);
+ return (blk);
+ }
sp = swdevhd;
- for (i = 0; i < nswapdev; i++) {
+ while (mpages >= limit) {
if (sp == NULL)
sp = TAILQ_FIRST(&swtailq);
- if (!(sp->sw_flags & SW_CLOSING)) {
- blk = blist_alloc(sp->sw_blist, npages);
- if (blk != SWAPBLK_NONE) {
- blk += sp->sw_first;
- sp->sw_used += npages;
- swap_pager_avail -= npages;
- swp_sizecheck();
- swdevhd = TAILQ_NEXT(sp, sw_list);
- goto done;
- }
- }
+ if ((sp->sw_flags & SW_CLOSING) == 0)
+ blk = blist_alloc(sp->sw_blist, &npages, mpages);
+ if (blk != SWAPBLK_NONE)
+ break;
sp = TAILQ_NEXT(sp, sw_list);
+ if (swdevhd == sp) {
+ mpages = npages - 1;
+ npages >>= 1;
+ }
}
- if (swap_pager_full != 2) {
- printf("swap_pager_getswapspace(%d): failed\n", npages);
- swap_pager_full = 2;
- swap_pager_almost_full = 1;
+ if (blk != SWAPBLK_NONE) {
+ *io_npages = npages;
+ blk += sp->sw_first;
+ sp->sw_used += npages;
+ swap_pager_avail -= npages;
+ swp_sizecheck();
+ swdevhd = TAILQ_NEXT(sp, sw_list);
+ } else {
+ if (swap_pager_full != 2) {
+ printf("swp_pager_getswapspace(%d): failed\n",
+ *io_npages);
+ swap_pager_full = 2;
+ swap_pager_almost_full = 1;
+ }
+ swdevhd = NULL;
}
- swdevhd = NULL;
-done:
mtx_unlock(&sw_dev_mtx);
return (blk);
}
@@ -886,35 +898,30 @@
int
swap_pager_reserve(vm_object_t object, vm_pindex_t start, vm_size_t size)
{
- int n = 0;
- daddr_t blk = SWAPBLK_NONE;
+ int i, n;
+ daddr_t blk;
vm_pindex_t beg = start; /* save start index */
daddr_t addr, n_free, s_free;
swp_pager_init_freerange(&s_free, &n_free);
VM_OBJECT_WLOCK(object);
- while (size) {
- if (n == 0) {
- n = BLIST_MAX_ALLOC;
- while ((blk = swp_pager_getswapspace(n)) == SWAPBLK_NONE) {
- n >>= 1;
- if (n == 0) {
- swp_pager_meta_free(object, beg, start - beg);
- VM_OBJECT_WUNLOCK(object);
- return (-1);
- }
- }
+ while (beg + size > start) {
+ n = min(BLIST_MAX_ALLOC, beg + size - start);
+ blk = swp_pager_getswapspace(&n, 1);
+ if (blk == SWAPBLK_NONE) {
+ swp_pager_meta_free(object, beg, start - beg);
+ VM_OBJECT_WUNLOCK(object);
+ return (-1);
}
- addr = swp_pager_meta_build(object, start, blk);
- if (addr != SWAPBLK_NONE)
+ for (i = 0; i < n; ++i) {
+ addr = swp_pager_meta_build(object, start + i, blk + i);
+ if (addr == SWAPBLK_NONE)
+ continue;
swp_pager_update_freerange(&s_free, &n_free, addr);
- --size;
- ++start;
- ++blk;
- --n;
+ }
+ start += n;
}
swp_pager_freeswapspace(s_free, n_free);
- swp_pager_meta_free(object, start, n);
VM_OBJECT_WUNLOCK(object);
return (0);
}
@@ -1384,18 +1391,8 @@
n = min(BLIST_MAX_ALLOC, count - i);
n = min(n, nsw_cluster_max);
- /*
- * Get biggest block of swap we can. If we fail, fall
- * back and try to allocate a smaller block. Don't go
- * overboard trying to allocate space if it would overly
- * fragment swap.
- */
- while (
- (blk = swp_pager_getswapspace(n)) == SWAPBLK_NONE &&
- n > 4
- ) {
- n >>= 1;
- }
+ /* Get a block of swap of size up to size n. */
+ blk = swp_pager_getswapspace(&n, 4);
if (blk == SWAPBLK_NONE) {
for (j = 0; j < n; ++j)
rtvals[i+j] = VM_PAGER_FAIL;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Oct 12, 7:02 PM (2 h, 37 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
23636916
Default Alt Text
D20001.id56784.diff (11 KB)
Attached To
Mode
D20001: Let swp_pager_getswapspace allocate bigger blocks
Attached
Detach File
Event Timeline
Log In to Comment