On Mon, Dec 10, 2018 at 11:44:47AM +0100, Otto Moerbeek wrote:

> On Mon, Dec 10, 2018 at 08:30:10AM +0100, Otto Moerbeek wrote:
> 
> > Hi,
> > 
> > the bootloader uses a very simple allocator for dynamic memory. It
> > maintains a list of free allocations. If it needs a block, it searches
> > the freelist and returns the smallest allocation that fits.
> > 
> > Allocation patterns like this (starting with an empty freelist)
> > 
> > alloc(big)
> > free(big)
> > alloc(small)
> > 
> > will assigned a big block for the small allocation, wasting most
> > memory. The allocator does not split up this block. After this, a new
> > big allocation will grow the heap with the big amount. This diff
> > changes the strategy by not re-using a block from the free list if
> > half the space or more would be wasted. Instead, it grows the heap by
> > the requested amount.
> > 
> > This make it possible for me to boot using a root fs with a large
> > blocksize. There have been several reports of large roots not working
> > (the bootloader allocates memory based om the blocksize of the file
> > system, and by default larger filesystems use larger blocks).
> > 
> > How to test
> > ===========
> > 
> > Apply diff and do a full build including building release. After that,
> > either upgrade using your newly built cd64.iso, bsd.rd or other
> > mechanism or do a full install. Test that you can boot afterwards.
> > 
> > This needs to be tested on various platforms, both will small and big
> > (> 600G) root filesystems.  Yes, this is tedious, but we want large
> > coverage of different cases.
> > 
> >     -Otto
> 
> As it turns out by my own testing, on amd64 root filssytems using 32k
> blocks now work fine, but 64k fs blocks still hit a ceiling. This
> corresponds to > 512G disks if you use the defaults.
> 
>       -Otto
> 

New diff that also works on root filesystems > 500G. It avoid using a
large bouncebuffer by reding large buffers in a loop instead of one go.

        -Otto

Index: arch/amd64/stand/libsa/biosdev.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/stand/libsa/biosdev.c,v
retrieving revision 1.32
diff -u -p -r1.32 biosdev.c
--- arch/amd64/stand/libsa/biosdev.c    10 Aug 2018 16:41:35 -0000      1.32
+++ arch/amd64/stand/libsa/biosdev.c    11 Dec 2018 13:00:02 -0000
@@ -340,11 +340,26 @@ biosd_io(int rw, bios_diskinfo_t *bd, u_
        return error;
 }
 
+#define MAXSECTS 32
+
 int
 biosd_diskio(int rw, struct diskinfo *dip, u_int off, int nsect, void *buf)
 {
-       return biosd_io(rw, &dip->bios_info, off, nsect, buf);
+       int i, n, ret;
+
+       /*
+        * Avoid doing too large reads, the bounce buffer used by biosd_io()
+        * might run us out-of-mem.
+        */
+       for (i = 0, ret = 0; ret == 0 && nsect > 0;
+           i += MAXSECTS, nsect -= MAXSECTS) {
+               n = nsect >= MAXSECTS ? MAXSECTS : nsect;
+               ret = biosd_io(rw, &dip->bios_info, off + i, n,
+                   buf + i * DEV_BSIZE);
+       }
+       return ret;
 }
+
 /*
  * Try to read the bsd label on the given BIOS device.
  */
@@ -715,7 +730,6 @@ biosstrategy(void *devdata, int rw, dadd
     size_t *rsize)
 {
        struct diskinfo *dip = (struct diskinfo *)devdata;
-       bios_diskinfo_t *bd = &dip->bios_info;
        u_int8_t error = 0;
        size_t nsect;
 
@@ -732,7 +746,7 @@ biosstrategy(void *devdata, int rw, dadd
        if (blk < 0)
                error = EINVAL;
        else
-               error = biosd_io(rw, bd, blk, nsect, buf);
+               error = biosd_diskio(rw, dip, blk, nsect, buf);
 
 #ifdef BIOS_DEBUG
        if (debug) {
Index: arch/i386/stand/libsa/biosdev.c
===================================================================
RCS file: /cvs/src/sys/arch/i386/stand/libsa/biosdev.c,v
retrieving revision 1.98
diff -u -p -r1.98 biosdev.c
--- arch/i386/stand/libsa/biosdev.c     6 Sep 2018 11:50:54 -0000       1.98
+++ arch/i386/stand/libsa/biosdev.c     11 Dec 2018 13:00:02 -0000
@@ -341,11 +341,26 @@ biosd_io(int rw, bios_diskinfo_t *bd, u_
        return error;
 }
 
+#define MAXSECTS 32
+
 int
 biosd_diskio(int rw, struct diskinfo *dip, u_int off, int nsect, void *buf)
 {
-       return biosd_io(rw, &dip->bios_info, off, nsect, buf);
+       int i, n, ret;
+
+       /*
+        * Avoid doing too large reads, the bounce buffer used by biosd_io()
+        * might run us out-of-mem.
+        */
+       for (i = 0, ret = 0; ret == 0 && nsect > 0;
+           i += MAXSECTS, nsect -= MAXSECTS) {
+               n = nsect >= MAXSECTS ? MAXSECTS : nsect;
+               ret = biosd_io(rw, &dip->bios_info, off + i, n,
+                   buf + i * DEV_BSIZE);
+       }
+       return ret;
 }
+
 /*
  * Try to read the bsd label on the given BIOS device.
  */
@@ -716,7 +731,6 @@ biosstrategy(void *devdata, int rw, dadd
     size_t *rsize)
 {
        struct diskinfo *dip = (struct diskinfo *)devdata;
-       bios_diskinfo_t *bd = &dip->bios_info;
        u_int8_t error = 0;
        size_t nsect;
 
@@ -733,7 +747,7 @@ biosstrategy(void *devdata, int rw, dadd
        if (blk < 0)
                error = EINVAL;
        else
-               error = biosd_io(rw, bd, blk, nsect, buf);
+               error = biosd_diskio(rw, dip, blk, nsect, buf);
 
 #ifdef BIOS_DEBUG
        if (debug) {
Index: lib/libsa/alloc.c
===================================================================
RCS file: /cvs/src/sys/lib/libsa/alloc.c,v
retrieving revision 1.12
diff -u -p -r1.12 alloc.c
--- lib/libsa/alloc.c   14 Mar 2016 23:08:06 -0000      1.12
+++ lib/libsa/alloc.c   11 Dec 2018 13:00:03 -0000
@@ -169,7 +169,7 @@ alloc(unsigned int size)
        }
 
        /* no match in freelist if bestsize unchanged */
-       failed = (bestsize == 0xffffffff);
+       failed = (bestsize == 0xffffffff || bestsize >= size * 2);
 #endif
 
        if (failed) { /* nothing found */

Reply via email to