On 12/11/18 08:09, Otto Moerbeek wrote:
> 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

You are my hero.
Seems it is possible to hose a system by making a 32k block size on a
system with a root file system of only 500MB.  I really don't know how I
did this, much less why, but it's been causing me reboot problems for
over a year now.

Upgraded to today's snap, problem solved.

Nick.

/home/nick $ dmesg|head  
OpenBSD 6.4-current (GENERIC.MP) #510: Thu Dec 13 06:20:42 MST 2018
    dera...@amd64.openbsd.org:/usr/src/sys/arch/amd64/compile/GENERIC.MP


> p m
OpenBSD area: 64-2000397735; size: 976756.7M; free: 859532.4M
#                size           offset  fstype [fsize bsize   cpg]
  a:           502.0M               64  4.2BSD   4096 32768     1 # / # wtf?
  b:         20473.5M       1048578560    swap                    # 
  c:        976762.3M                0  unused                    
  d:         10244.6M       1090508288  4.2BSD   2048 16384     1 # /usr
  e:          4094.7M       1111489152  4.2BSD   2048 16384     1 # /tmp
  f:         10236.7M       1119875072  4.2BSD   2048 16384     1 # /var
  g:         20473.5M       1161804704  4.2BSD   2048 16384     1 # /repo
  h:         10236.7M       1140839904  4.2BSD   2048 16384     1 # /home
  i:             7.8M       1203734368  4.2BSD   2048 16384     1 # 
  j:         40954.8M       1203750432  4.2BSD   2048 16384     1 


> 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