[Ocfs2-tools-devel] Add compress dirs option in fsck.ocfs2 [v3]

Goldwyn Rodrigues rgoldwyn at gmail.com
Fri Oct 16 13:03:08 PDT 2009


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.

Signed-off-by: Goldwyn Rodrigues <rgoldwyn at suse.de>

--- 
diff --git a/fsck.ocfs2/fsck.c b/fsck.ocfs2/fsck.c
index 4e9b300..6fdc02a 100644
--- a/fsck.ocfs2/fsck.c
+++ b/fsck.ocfs2/fsck.c
@@ -653,7 +653,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);
@@ -678,6 +678,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;
@@ -728,6 +731,13 @@ int main(int argc, char **argv)
 		}
 	}
 
+	if (!(open_flags & OCFS2_FLAG_RW) && ost->ost_compress_dirs) {
+		fprintf(stderr, "Compress directories (-D) incompatible with read-only mode\n");
+		fsck_mask |= FSCK_USAGE;
+		print_usage();
+		goto out;
+	}
+
 	if (blksize % OCFS2_MIN_BLOCKSIZE) {
 		fprintf(stderr, "Invalid blocksize: %"PRId64"\n", blksize);
 		fsck_mask |= FSCK_USAGE;
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