[Ocfs2-tools-devel] Add compress dirs option in fsck.ocfs2
Goldwyn Rodrigues
rgoldwyn at gmail.com
Mon Aug 31 16:47:00 PDT 2009
This attempt is after incorporating Joel's comments.
This patch adds the option to compress directories (-D) in fsck.
The option compresses the directory entries and consolidates a hole at
the end of the directory block. This consolidated hole increases the
chance of ocfs2_prepare_dir_for_insert (kmp) to find a hole using
ocfs2_find_dir_space_* functions while inserting a new directory entry
in the directory.
---
diff --git a/fsck.ocfs2/fsck.c b/fsck.ocfs2/fsck.c
index 74c18ac..57310a9 100644
--- a/fsck.ocfs2/fsck.c
+++ b/fsck.ocfs2/fsck.c
@@ -650,7 +650,7 @@ int main(int argc, char **argv)
setlinebuf(stderr);
setlinebuf(stdout);
- while((c = getopt(argc, argv, "b:B:fFGnuvVyr:")) != EOF) {
+ while((c = getopt(argc, argv, "b:B:DfFGnuvVyr:")) != EOF) {
switch (c) {
case 'b':
blkno = read_number(optarg);
@@ -675,6 +675,9 @@ int main(int argc, char **argv)
goto out;
}
break;
+ case 'D':
+ ost->ost_compress_dirs = 1;
+ break;
case 'F':
ost->ost_skip_o2cb = 1;
diff --git a/fsck.ocfs2/include/fsck.h b/fsck.ocfs2/include/fsck.h
index 240286c..a533aad 100644
--- a/fsck.ocfs2/include/fsck.h
+++ b/fsck.ocfs2/include/fsck.h
@@ -73,7 +73,8 @@ typedef struct _o2fsck_state {
ost_stale_mounts:1, /* set when reading publish blocks
* that still indicated mounted */
ost_fix_fs_gen:1,
- ost_has_journal_dirty:1;
+ ost_has_journal_dirty:1,
+ ost_compress_dirs:1;
errcode_t ost_err;
} o2fsck_state;
diff --git a/fsck.ocfs2/pass2.c b/fsck.ocfs2/pass2.c
index 810bf10..d61c501 100644
--- a/fsck.ocfs2/pass2.c
+++ b/fsck.ocfs2/pass2.c
@@ -668,6 +668,7 @@ static unsigned pass2_dir_block_iterate(o2fsck_dirblock_entry *dbe,
struct dirblock_data *dd = priv_data;
struct ocfs2_dir_entry *dirent, *prev = NULL;
unsigned int offset = 0, ret_flags = 0, end = dd->fs->fs_blocksize;
+ unsigned int write_off, saved_reclen;
struct ocfs2_dinode *di = (struct ocfs2_dinode *)dd->inoblock_buf;
errcode_t ret = 0;
@@ -723,6 +724,8 @@ static unsigned pass2_dir_block_iterate(o2fsck_dirblock_entry *dbe,
end = ocfs2_dir_trailer_blk_off(dd->fs);
}
+ write_off = offset;
+
while (offset < end) {
dirent = (struct ocfs2_dir_entry *)(dd->dirblock_buf + offset);
@@ -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;
}
if (ocfs2_dir_has_trailer(dd->fs, di))
diff --git a/libocfs2/dir_iterate.h b/libocfs2/dir_iterate.h
index f281af2..2d9587b 100644
--- a/libocfs2/dir_iterate.h
+++ b/libocfs2/dir_iterate.h
@@ -49,4 +49,11 @@ extern int ocfs2_process_dir_block(ocfs2_filesys *fs,
uint16_t ext_flags,
void *priv_data);
+#define OCFS2_DIR_PAD 4
+#define OCFS2_DIR_ROUND (OCFS2_DIR_PAD - 1)
+#define OCFS2_DIR_MEMBER_LEN offsetof(struct ocfs2_dir_entry, name)
+#define OCFS2_DIR_REC_LEN(name_len) (((name_len) + OCFS2_DIR_MEMBER_LEN + \
+ OCFS2_DIR_ROUND) & \
+ ~OCFS2_DIR_ROUND)
+
#endif /* _DIR_ITERATE_H */
More information about the Ocfs2-tools-devel
mailing list