[Ocfs2-tools-devel] [PATCH 08/11] fsck.ocfs2 now know inline data.
Tao Ma
tao.ma at oracle.com
Tue Jul 22 15:52:27 PDT 2008
fsck.ocfs2 will only check i_size and i_clusters for inline data.
As for directory check, inline directory will also be checked.
Signed-off-by: Tao Ma <tao.ma at oracle.com>
---
fsck.ocfs2/pass1.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++--
fsck.ocfs2/pass2.c | 52 ++++++++++++++++++++++++++++++++++++++--------------
2 files changed, 86 insertions(+), 16 deletions(-)
diff --git a/fsck.ocfs2/pass1.c b/fsck.ocfs2/pass1.c
index bef2863..dbb9584 100644
--- a/fsck.ocfs2/pass1.c
+++ b/fsck.ocfs2/pass1.c
@@ -767,6 +767,24 @@ static errcode_t o2fsck_check_blocks(ocfs2_filesys *fs, o2fsck_state *ost,
(S_ISLNK(di->i_mode) && di->i_clusters == 0))
return 0;
+ if (di->i_dyn_features & OCFS2_INLINE_DATA_FL) {
+ /*
+ * We add i_blkno as the dir block, so when the dir's
+ * inode_no is the same as dir_block_no, we can tell
+ * that this dir is inlinded and help us in the following
+ * directory check.
+ */
+ if (S_ISDIR(di->i_mode)) {
+ ret = o2fsck_add_dir_block(&ost->ost_dirblocks,
+ di->i_blkno,
+ di->i_blkno, 0);
+ if (ret)
+ return ret;
+ }
+
+ goto size_cluster_check;
+ }
+
ret = o2fsck_check_extents(ost, di);
if (ret == 0)
ret = ocfs2_block_iterate_inode(fs, di,
@@ -816,6 +834,7 @@ static errcode_t o2fsck_check_blocks(ocfs2_filesys *fs, o2fsck_state *ost,
goto out;
}
+size_cluster_check:
/*
* i_size and i_cluster mean quite different between a non-sparse
* and sparse file system.
@@ -831,9 +850,36 @@ static errcode_t o2fsck_check_blocks(ocfs2_filesys *fs, o2fsck_state *ost,
* end of the visible cluster end. It is also reasonable for a file
* which has no allocated blocks but any number of byte sizes,
* so we don't need to check its size either.
+ *
+ * In an inline file, i_clusters should be zero and i_size should be
+ * less than the max inline data size.
*/
- if (OCFS2_RAW_SB(fs->fs_super)->s_feature_incompat &
- OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC) {
+ if (di->i_dyn_features & OCFS2_INLINE_DATA_FL) {
+ expected = ocfs2_max_inline_data(fs->fs_blocksize);
+
+ /* i_size is checked for symlinks elsewhere */
+ if (di->i_size > expected &&
+ prompt(ost, PY, PR_INODE_SIZE, "Inode %"PRIu64
+ " has a size of %"PRIu64" which exceeds the max "
+ " inline data size %"PRIu64". "
+ "Correct the file size?",
+ (uint64_t)di->i_blkno, (uint64_t)di->i_size,
+ expected)) {
+ di->i_size = expected;
+ o2fsck_write_inode(ost, blkno, di);
+ }
+
+ if (di->i_clusters > 0 &&
+ prompt(ost, PY, PR_INODE_CLUSTERS,
+ "Inode %"PRIu64" has %"PRIu32" clusters but it has "
+ "inline data flag set. "
+ "Correct the number of clusters?",
+ (uint64_t)di->i_blkno, di->i_clusters)) {
+ di->i_clusters = 0;
+ o2fsck_write_inode(ost, blkno, di);
+ }
+ } else if (OCFS2_RAW_SB(fs->fs_super)->s_feature_incompat &
+ OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC) {
if (vb.vb_num_blocks > 0) {
expected = ocfs2_blocks_to_clusters(fs,
vb.vb_last_block + 1);
diff --git a/fsck.ocfs2/pass2.c b/fsck.ocfs2/pass2.c
index 5f1696d..c53c264 100644
--- a/fsck.ocfs2/pass2.c
+++ b/fsck.ocfs2/pass2.c
@@ -83,12 +83,19 @@ static int dirent_has_dots(struct ocfs2_dir_entry *dirent, int num_dots)
return dirent->name[0] == '.';
}
-static int expected_dots(o2fsck_dirblock_entry *dbe, int offset)
+static int expected_dots(o2fsck_state *ost,
+ o2fsck_dirblock_entry *dbe,
+ int offset)
{
+ int inline_off = offsetof(struct ocfs2_dinode, id2.i_data.id_data);
+
if (dbe->e_blkcount == 0) {
- if (offset == 0)
+ if (offset == 0 ||
+ (dbe->e_ino == dbe->e_blkno && offset == inline_off))
return 1;
- if (offset == OCFS2_DIR_REC_LEN(1))
+ if (offset == OCFS2_DIR_REC_LEN(1) ||
+ (dbe->e_ino == dbe->e_blkno &&
+ offset == inline_off + OCFS2_DIR_REC_LEN(1)))
return 2;
}
@@ -99,7 +106,7 @@ static errcode_t fix_dirent_dots(o2fsck_state *ost, o2fsck_dirblock_entry *dbe,
struct ocfs2_dir_entry *dirent, int offset,
int left, unsigned int *flags)
{
- int expect_dots = expected_dots(dbe, offset);
+ int expect_dots = expected_dots(ost, dbe, offset);
int changed_len = 0;
struct ocfs2_dir_entry *next;
uint16_t new_len;
@@ -432,7 +439,7 @@ static errcode_t fix_dirent_linkage(o2fsck_state *ost,
int offset,
unsigned int *flags)
{
- int expect_dots = expected_dots(dbe, offset);
+ int expect_dots = expected_dots(ost, dbe, offset);
o2fsck_dir_parent *dp;
errcode_t ret = 0;
int is_dir;
@@ -637,14 +644,25 @@ static unsigned pass2_dir_block_iterate(o2fsck_dirblock_entry *dbe,
verbosef("dir block %"PRIu64" block offs %"PRIu64" in ino\n",
dbe->e_blkno, dbe->e_blkcount);
- if (dbe->e_blkcount >= ocfs2_blocks_in_bytes(dd->fs, di->i_size))
- goto out;
+ if (di->i_dyn_features & OCFS2_INLINE_DATA_FL) {
+ if (dbe->e_ino != dbe->e_blkno)
+ goto out;
- ret = ocfs2_read_dir_block(dd->fs, dbe->e_blkno, dd->dirblock_buf);
- if (ret && ret != OCFS2_ET_DIR_CORRUPTED) {
- com_err(whoami, ret, "while reading dir block %"PRIu64,
- dbe->e_blkno);
- goto out;
+ memcpy(dd->dirblock_buf, dd->inoblock_buf,
+ dd->fs->fs_blocksize);
+ offset = offsetof(struct ocfs2_dinode, id2.i_data.id_data);
+ } else {
+ if (dbe->e_blkcount >= ocfs2_blocks_in_bytes(dd->fs,
+ di->i_size))
+ goto out;
+
+ ret = ocfs2_read_dir_block(dd->fs, dbe->e_blkno,
+ dd->dirblock_buf);
+ if (ret && ret != OCFS2_ET_DIR_CORRUPTED) {
+ com_err(whoami, ret, "while reading dir block %"PRIu64,
+ dbe->e_blkno);
+ goto out;
+ }
}
while (offset < dd->fs->fs_blocksize) {
@@ -735,8 +753,14 @@ next:
}
if (ret_flags & OCFS2_DIRENT_CHANGED) {
- ret = ocfs2_write_dir_block(dd->fs, dbe->e_blkno,
- dd->dirblock_buf);
+ if (di->i_dyn_features & OCFS2_INLINE_DATA_FL) {
+ memcpy(dd->inoblock_buf, dd->dirblock_buf,
+ dd->fs->fs_blocksize);
+ ret = ocfs2_write_inode(dd->fs, dbe->e_ino,
+ dd->dirblock_buf);
+ } else
+ ret = ocfs2_write_dir_block(dd->fs, dbe->e_blkno,
+ dd->dirblock_buf);
if (ret) {
com_err(whoami, ret, "while writing dir block %"PRIu64,
dbe->e_blkno);
--
1.5.4.GIT
More information about the Ocfs2-tools-devel
mailing list