[Ocfs2-tools-devel] [PATCH] Compress dirs option in fsck

Goldwyn Rodrigues rgoldwyn at gmail.com
Mon Aug 31 15:24:06 PDT 2009


Hi,

Thanks for the review.

On Wed, Aug 26, 2009 at 05:57:01PM -0700, Joel Becker wrote:
> On Wed, Aug 19, 2009 at 05:14:59PM -0500, Goldwyn Rodrigues wrote:
<snipped>
> 
> 	You need to use memmove() here.  Even if the memory work didn't
> overlap (and it can), saving a cycle or two isn't going to matter when
> our limiting factor is the dirblock I/O.

Okay. since the write index is always lower, I thought it would be fine.
However, memmove() is safer.

> 
> > +				memcpy(dd->dirblock_buf + write_off,
> > +						dd->dirblock_buf + offset,
> > +						dirent->rec_len);
> > +				dirent = dd->dirblock_buf + write_off;
> 
> 	This needs a cast as you assign it.
> 

Yes, I have incorporated this in the next patch.

> >  	}
> 
> 	What happens if:
> 
> 1) The first dirent is an empty one.
> 2) The second dirent has a problem that is fixed.  DIRENT_CHANGED is set.
>    The second dirent is memmove()d to the front of the block, with
>    dirent->rec_len = REC_LEN(name_len).
> 3) The third dirent has a problem that cannot be fixed, and we jump to
>    out:
> 4) ocfs2_dir_block_iterate() writes the dirblock because of
>    DIRENT_CHANGED.

Oh yes, I missed this case.

> 
> 	What you'll have is a new first dirent with a rec_len that
> doesn't cover the space between it and the next dirent.  The next fsck
> will then be forced to wipe the entire dirblock.
> 	Instead, when you shift a dirent, you need to set its rec_len to
> cover the space between its new location and its old end.    Something
> like:
> 
> +		saved_reclen=dirent->rec_len;
> +		if ((dd->ost->ost_rehash_dirs) && dirent->inode) {
> +			if (write_off < offset) {
> +				/* Bring prev->rec_len back to write_off */
> +				if (prev)
> +					prev->rec_len =
> +						OCFS2_DIR_REC_LEN(prev->name_len);
> +				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 = dd->dirblock_buf + write_off;
> +				/* Cover space from our new location to
> +				 * the next dirent */
> +				dirent->rec_len = offset + saved_reclen
> +					- write_off;
> +			}
> +			write_off += OCFS2_DIR_REC_LEN(dirent->name_len);
> +			ret_flags |= OCFS2_DIRENT_CHANGED;
> +		}
> 

I changed it a bit to compute the write_off in the starting of the block
for the consecutive entry. It is just easier to handle. I will post the
updated patch soon once I have done my share of testing.

Thanks,

-- 
Goldwyn



More information about the Ocfs2-tools-devel mailing list