improve fs check console command (see fs(8)) the original code could try to put things at the end of a completely full, or nearly full bank of memory. as the code notes, ialloc(0, 1) doesn't allocate any memory, so a memory bank doesn't need any memory to match. add getbrk() to find a sutable hole, and give it a chance to do the write thing by making a good guess at the sizes required. also, use the superblock's qidgen to size the qid bitmap, rather than using a constant. it may be necessary to longjmp back to the beginning if we've sized things incorrectly. it's really annoying to panic during a check. these changes may be applicable to cwfs, but that's for another day. i'd like to build a new cwfs from the same source as the fileserver. Reference: /n/atom/patch/applied/fschk Date: Tue Apr 15 20:28:59 CES 2014 Signed-off-by: quanstro@quanstro.net --- /sys/src/fs/port/chk.c Tue Apr 15 20:19:43 2014 +++ /sys/src/fs/port/chk.c Tue Apr 15 20:19:43 2014 @@ -8,9 +8,9 @@ } Extdentry; static char* abits; -static long sizabits; +static Off sizabits; static char* qbits; -static long sizqbits; +static Off sizqbits; static char* name; static long sizname; @@ -55,15 +55,65 @@ static void qmark(Off); static Iobuf* xtag(Off, int, Off); +static struct { + uchar *base; + uchar *end; +} mal; + +void* +getbrk(uintptr n) +{ + Mbank *b; + uintmem p, align; + int m; + + n += 100000; /* fake safety */ + align = sizeof(uintptr); + + ilock(&mconf); + for(b = mconf.bank; b < mconf.bank+mconf.nbank; b++){ + p = b->base; + + if(align <= 0) + align = sizeof(uintptr); + if(m = n % align) + n += align - m; + if(m = p % align) + p += align - m; + + if(p+n > b->limit) + continue; + + iunlock(&mconf); + + mal.base = KADDR(p); + mal.end = KADDR(p+n); + memset(mal.base, 0, n); + return mal.base; + } + + iunlock(&mconf); + + print("not enough memory %lld\n", n); + return nil; +} + +void +putbrk(void) +{ + mal.base = nil; + mal.end = nil; +}; + void* -malloc(ulong n) +malloc(usize n) { char *p, *q; - p = (char *)ROUNDUP((uintptr)calloc, BY2WD); + p = (char *)ROUNDUP((uintptr)calloc, sizeof(uintptr)); q = p+n; - if(PADDR(q) >= conf.mem) - panic("check: mem size"); + if(q >= (char*)mal.end) + panic("check: mem size: %#p %#p %ld", q, mal.end, n); calloc = q; memset(p, 0, n); return p; @@ -134,18 +184,9 @@ cwflag = (dev->type == Devcw) | (dev->type == Devro); if(!ronly) wlock(&mainlock); /* check */ - /* - * ialloc(0, 1) doesn't actually allocate any storage, and may - * return the same address each time. see iobufinit(). - * check assumes that the rest of memory, from ialloc(0, 1) - * up, is available to it, but does at least check in malloc(). - */ - calloc = (char*)ialloc(0, 1) + 100000; flags = flag; - sizqbits = ((1<<23) + 7) / 8; /* botch; guess at max qid */ - qbits = malloc(sizqbits); - + /* guess at bitmap size */ sbaddr = superaddr(dev); raddr = getraddr(dev); p = xtag(sbaddr, Tsuper, QPSUPER); @@ -156,7 +197,20 @@ cons.noage = 1; fsize = sb->fsize; + + /* + * use getbrk, fake malloc, hope, and chewing gum to try to + * find a hole in memory that won't collide with anything. + * memory is returned when we're done. + */ + sizqbits = (sb->qidgen+sb->qidgen/2 + 7) / 8; /* botch. allow for qidgen/2 modified files */ sizabits = (fsize-fstart + 7)/8; + calloc = (char*)getbrk(sizqbits + sizabits + 4000 + 10000*sizeof(Dentry)); /* botch: 10000 directories */ + if(calloc == nil){ + print("insufficient memory: sizqbits %lld sizabits %lld\n", (uvlong)sizqbits, (uvlong)sizabits); + return; + } + qbits = malloc(sizqbits); abits = malloc(sizabits); sizname = 4000; @@ -246,6 +300,7 @@ putbuf(p); if(!ronly) wunlock(&mainlock); + putbrk(); } /*