e8b68c4e88
Hopefully third times the charm. The previous solution pretty bluntly did not work outside of the recursive remove case, because the moment we mark the rid as deleted, the directory positions no longer get updates. It's not possible to update the directory position because we don't know how it maps into our mtree without a full seek from the dstart. After staring at it a bit, I think this solution should work: 1. Instead of marking the mid/rid as removed when dropping an mdir, we set the weight to zero and the trunk to zero, causing mdir lookups to return NOENT without actually going to disk. This is very important since later mdirs could be allocated on the same block, and going to disk can result in a corrupted lookup. 2. Eagerly seek to the next mid/rid after every lfsr_dir_read call. This puts us in a position where rid can be >= the current mdir weight without issues, and avoids degenerate cases that may be caused by recursive removes. 3. If we remove an opened dir, instead of marking the mdir as deleted, move the rid to the next rid. If the mdir was dropped, this leaves us with rid == mdir weight, and the mdir trunk == 0. The rid == mdir weight also occurs when we are creating a new file, so we have a bit of common behavior we can rely on. We just need to make sure that mdir updates respect the rid == mdir weight situation. 4. On each lfsr_dir_read call, we do an mtree seek of zero. This just serves to fix our mdir if our rid == mdir weight, without much additional code (yay for code reuse). The use of weight=0, trunk=0, for a dropped mdir here is key, and makes me wonder if this is a better indicator of a dropped mdir than another reserved mid value. This probably deserves some investigation later.