[Ocfs2-tools-devel] Add compress dirs option in fsck.ocfs2
Goldwyn Rodrigues
rgoldwyn at gmail.com
Tue Sep 1 16:08:39 PDT 2009
Hi,
On Tue, Sep 1, 2009 at 3:29 PM, Joel Becker<Joel.Becker at oracle.com> wrote:
> On Mon, Aug 31, 2009 at 06:47:00PM -0500, Goldwyn Rodrigues wrote:
>> @@ -804,8 +807,29 @@ static unsigned pass2_dir_block_iterate(o2fsck_dirblock_entry *dbe,
>> dirent->name, (uint64_t)dirent->inode);
>> o2fsck_icount_delta(dd->ost->ost_icount_refs, dirent->inode, 1);
>> next:
>> - offset += dirent->rec_len;
>> + saved_reclen = dirent->rec_len;
>> + if (dd->ost->ost_compress_dirs) {
>> + if (prev && prev->inode) {
>> + /*Bring previous rec_len to required space */
>> + prev->rec_len = OCFS2_DIR_REC_LEN(prev->name_len);
>> + write_off += prev->rec_len;
>> + }
>> + if (write_off < offset) {
>> + verbosef("ino: %llu woff: %u off: %u\n",
>> + dirent->inode, write_off, offset);
>> + memmove(dd->dirblock_buf + write_off,
>> + dd->dirblock_buf + offset,
>> + OCFS2_DIR_REC_LEN(dirent->name_len));
>> + dirent = (struct ocfs2_dir_entry *)(dd->dirblock_buf + write_off);
>> + /* Cover space from our new location to
>> + * the next dirent */
>> + dirent->rec_len = saved_reclen + offset - write_off;
>> +
>> + ret_flags |= OCFS2_DIRENT_CHANGED;
>> + }
>> + }
>> prev = dirent;
>> + offset += saved_reclen;
>> }
>
> Two things. First, what about empty records? Imagine you've
> just seen a dirent, set its rec_len to saved_reclen+offset-write_off.
> You set prev=dirent. Then next pass is a deleted dirent, dirent->inode
> = 0. You skip this block and set prev=dirent. Then you come to another
> valid dirent. However, prev->inode is zero, and so you won't update the
> first dirent's rec_len, nor will you update write_off correctly.
No, I do not skip the dirent record if dirent->inode==0. I still
memmove() it and set prev to dirent (the empty one).
prev is responsible for skipping empty records (by not updating write_off)
> Second thing, when you reach the end of the block there is no
> guarantee the last dirent->rec_len covers the entire block. It will if
> it was the last dirent, but not if there were empty ones after it.
I was not aware of this. I thought that there are no empty records
trailing the last dir_entry, and the last dir_entry always covered the
rest of the block. What condition would create this situation?
--
Goldwyn
More information about the Ocfs2-tools-devel
mailing list