From mboxrd@z Thu Jan 1 00:00:00 1970 Message-ID: <86d7b1bda15f1dbeba599814a88c12dc@rei2.9hal> Date: Tue, 26 Mar 2013 19:34:29 +0100 From: cinap_lenrek@gmx.de To: 9fans@9fans.net In-Reply-To: <640205b4834b5059f5ba5ff0d8d4ccc3@brasstown.quanstro.net> MIME-Version: 1.0 Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: 7bit Subject: Re: [9fans] Disk backup? Topicbox-Message-UUID: 3687adf4-ead8-11e9-9d60-3106f5b1d025 i looked at kenfs's dumpblock() from /n/sources/extra/fs/fs/dev/cw.c but i do not see what you mean. the code just goes thru the cache looking for a block to dump while trying to get one as close to the previous dumped block address as possible in both directions. (trying to avoid seeks?) can you point to the specific code that makes sure that blocks get only written to the worm after the previous superblock? what makes me think (i could be wrong here) that the assumption does *not* hold is this (using kenfs here from /n/sources/extra/fs): blocks have the following states: /* states -- beware these are recorded on the cache */ /* cache worm */ Cnone = 0, /* 0 ? */ Cdirty, /* 1 0 */ Cdump, /* 1 0->1 */ Cread, /* 1 1 */ Cwrite, /* 2 1 */ Cdump1, /* inactive form of dump */ Cerror, the blocks maintained in the freelist should be blocks not already written to the worm. like, when we delete a file that was already written to the worm (states Cread, Cwrite), it is not put into the freelist and we'll just forget about it. however, if the block was just in the cache (Cdirty) it *is* put on the freelist: int cwfree(Device *dev, Off addr) { int state; if(dev->type == Devcw) { state = cwio(dev, addr, 0, Ofree); if(state != Cdirty) return 1; /* do not put in freelist */ } return 0; /* put in freelist */ } now, such a Cdirty block could just sit in the freelist for a while no? while the filesystem does many dump generations. if that Cdirty block becomes part of the filesystem again because it is allocated, then the next cwrecur() should pick it up and call split() on it. Off split(Cw *cw, Iobuf *p, Off addr) { Off na; int state; na = 0; if(p && (p->flags & Bmod)) { p->flags |= Bimm; putbuf(p); p = 0; } state = cwio(cw->dev, addr, 0, Onone); /* read the state (twice?) */ switch(state) { default: panic("split: unknown state %s", cwnames[state]); case Cerror: case Cnone: case Cdump: case Cread: break; case Cdump1: case Cwrite: /* * botch.. could be done by relabeling */ if(!p) { p = getbuf(cw->dev, addr, Bread); if(!p) { print("split: null getbuf\n"); break; } } na = cw->fsize; cw->fsize = na+1; cwio(cw->dev, na, 0, Ogrow); cwio(cw->dev, na, p->iobuf, Owrite); cwio(cw->dev, na, 0, Odump); cwio(cw->dev, addr, 0, Orele); break; case Cdirty: cwio(cw->dev, addr, 0, Odump); // <- *here* break; } if(p) putbuf(p); return na; } we see in this case, that we wont make a new address for the block, but we'll just mark it for dumping at its original address which i think is not limited to after the last dumps superblock address. in the other case, when that block already had a version in the worm (Cdump1, Cwrite) it is indeed copied to the end of the filesystem like i think you ment by saying it will fill the worm only after the previous dumped superblock. does this make any sense? -- cinap