[Ocfs2-tools-devel] [PATCH 8/9] ocfs2-tools: add xattr support in fsck.ocfs2
Tiger Yang
tiger.yang at oracle.com
Fri Dec 19 01:42:05 PST 2008
This patch will check all extended attributes related with each inode,
It will check xattr extent tree in index block and xattr's value tree,
mark all xattr block/cluster as used.
Signed-off-by: Tiger Yang <tiger.yang at oracle.com>
---
fsck.ocfs2/Makefile | 3 +-
fsck.ocfs2/extent.c | 17 +---
fsck.ocfs2/include/extent.h | 13 +++
fsck.ocfs2/include/xattr.h | 26 +++++
fsck.ocfs2/pass1.c | 4 +
fsck.ocfs2/xattr.c | 249 +++++++++++++++++++++++++++++++++++++++++++
6 files changed, 296 insertions(+), 16 deletions(-)
create mode 100644 fsck.ocfs2/include/xattr.h
create mode 100644 fsck.ocfs2/xattr.c
diff --git a/fsck.ocfs2/Makefile b/fsck.ocfs2/Makefile
index d9d0862..9249cb5 100644
--- a/fsck.ocfs2/Makefile
+++ b/fsck.ocfs2/Makefile
@@ -31,7 +31,8 @@ CFILES = fsck.c \
problem.c \
slot_recovery.c \
strings.c \
- util.c
+ util.c \
+ xattr.c
HFILES = include/fsck.h \
include/dirblocks.h \
diff --git a/fsck.ocfs2/extent.c b/fsck.ocfs2/extent.c
index 665704d..5f6639c 100644
--- a/fsck.ocfs2/extent.c
+++ b/fsck.ocfs2/extent.c
@@ -46,19 +46,6 @@
static const char *whoami = "extent.c";
-struct extent_info {
- uint64_t ei_max_size;
- uint64_t ei_clusters;
- uint64_t ei_last_eb_blk;
- uint16_t ei_expected_depth;
- unsigned ei_expect_depth:1;
-};
-
-static errcode_t check_el(o2fsck_state *ost, struct extent_info *ei,
- struct ocfs2_dinode *di,
- struct ocfs2_extent_list *el,
- uint16_t max_recs, int *changed);
-
static errcode_t check_eb(o2fsck_state *ost, struct extent_info *ei,
struct ocfs2_dinode *di, uint64_t blkno,
int *is_valid)
@@ -233,7 +220,7 @@ out:
return ret;
}
-static errcode_t check_el(o2fsck_state *ost, struct extent_info *ei,
+errcode_t check_el(o2fsck_state *ost, struct extent_info *ei,
struct ocfs2_dinode *di,
struct ocfs2_extent_list *el,
uint16_t max_recs, int *changed)
@@ -373,4 +360,4 @@ errcode_t o2fsck_check_extents(o2fsck_state *ost,
o2fsck_write_inode(ost, di->i_blkno, di);
return ret;
-}
+}
diff --git a/fsck.ocfs2/include/extent.h b/fsck.ocfs2/include/extent.h
index 6fff28b..1266b7f 100644
--- a/fsck.ocfs2/include/extent.h
+++ b/fsck.ocfs2/include/extent.h
@@ -22,8 +22,21 @@
#include "fsck.h"
+struct extent_info {
+ uint64_t ei_max_size;
+ uint64_t ei_clusters;
+ uint64_t ei_last_eb_blk;
+ uint16_t ei_expected_depth;
+ unsigned ei_expect_depth:1;
+};
+
errcode_t o2fsck_check_extents(o2fsck_state *ost,
struct ocfs2_dinode *di);
+errcode_t check_el(o2fsck_state *ost, struct extent_info *ei,
+ struct ocfs2_dinode *di,
+ struct ocfs2_extent_list *el,
+ uint16_t max_recs, int *changed);
+
#endif /* __O2FSCK_EXTENT_H__ */
diff --git a/fsck.ocfs2/include/xattr.h b/fsck.ocfs2/include/xattr.h
new file mode 100644
index 0000000..382e3b6
--- /dev/null
+++ b/fsck.ocfs2/include/xattr.h
@@ -0,0 +1,26 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * xattr.h
+ *
+ * Copyright (C) 2004, 2008 Oracle. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+#ifndef __O2FSCK_XATTR_H__
+#define __O2FSCK_XATTR_H__
+
+#include "fsck.h"
+
+errcode_t o2fsck_check_xattr(o2fsck_state *ost,
+ struct ocfs2_dinode *di);
+
+#endif /* __O2FSCK_XATTR_H__ */
+
diff --git a/fsck.ocfs2/pass1.c b/fsck.ocfs2/pass1.c
index 209f8ff..6f385f6 100644
--- a/fsck.ocfs2/pass1.c
+++ b/fsck.ocfs2/pass1.c
@@ -65,6 +65,7 @@
#include "pass1.h"
#include "problem.h"
#include "util.h"
+#include "xattr.h"
static const char *whoami = "pass1";
@@ -1385,6 +1386,9 @@ errcode_t o2fsck_pass1(o2fsck_state *ost)
blkno, di);
if (ret)
goto out;
+ ret = o2fsck_check_xattr(ost, di);
+ if (ret)
+ goto out;
}
valid = di->i_flags & OCFS2_VALID_FL;
diff --git a/fsck.ocfs2/xattr.c b/fsck.ocfs2/xattr.c
new file mode 100644
index 0000000..76e8fea
--- /dev/null
+++ b/fsck.ocfs2/xattr.c
@@ -0,0 +1,249 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * xattr.c
+ *
+ * Copyright (C) 2004, 2008 Oracle. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+#include <string.h>
+#include <inttypes.h>
+
+#include "ocfs2/byteorder.h"
+#include "ocfs2/ocfs2.h"
+
+#include "xattr.h"
+#include "extent.h"
+#include "fsck.h"
+#include "problem.h"
+#include "util.h"
+
+static const char *whoami = "xattr.c";
+
+static errcode_t check_xattr(o2fsck_state *ost,
+ struct ocfs2_dinode *di,
+ struct ocfs2_xattr_header *xh,
+ int *changed)
+{
+ int i;
+ struct extent_info ei = {0, };
+ errcode_t ret = 0;
+
+ for (i = 0 ; i < xh->xh_count; i++) {
+ int change = 0;
+ struct ocfs2_xattr_entry *xe = &xh->xh_entries[i];
+
+ if (!ocfs2_xattr_is_local(xe)) {
+ struct ocfs2_xattr_value_root *xv =
+ (struct ocfs2_xattr_value_root *)
+ ((void *)xh + xe->xe_name_offset +
+ OCFS2_XATTR_SIZE(xe->xe_name_len));
+ struct ocfs2_extent_list *el = &xv->xr_list;
+ ret = check_el(ost, &ei, di, el, 1, &change);
+ if (ret)
+ return ret;
+ if (change)
+ *changed = 1;
+ }
+ }
+
+ return ret;
+}
+
+static errcode_t ocfs2_check_xattr_buckets(o2fsck_state *ost,
+ struct ocfs2_dinode *di,
+ uint64_t blkno,
+ uint32_t clusters)
+{
+ int i;
+ errcode_t ret = 0;
+ char *bucket = NULL;
+ struct ocfs2_xattr_header *xh;
+ int blk_per_bucket = ocfs2_blocks_per_xattr_bucket(ost->ost_fs);
+ uint32_t bpc = ocfs2_xattr_buckets_per_cluster(ost->ost_fs);
+ uint32_t num_buckets = clusters * bpc;
+
+ ret = ocfs2_malloc_blocks(ost->ost_fs->fs_io, blk_per_bucket, &bucket);
+ if (ret) {
+ com_err(whoami, ret, "while allocating room to read bucket "
+ "of xattr data");
+ goto out;
+ }
+
+ for (i = 0; i < num_buckets; i++, blkno += blk_per_bucket) {
+ int changed = 0;
+
+ ret = io_read_block(ost->ost_fs->fs_io, blkno,
+ blk_per_bucket, bucket);
+ if (ret) {
+ com_err(whoami, ret, "while reading blocks of xattr "
+ "bucket");
+ goto out;
+ }
+
+ xh = (struct ocfs2_xattr_header *)bucket;
+ ocfs2_swap_xattr_header(xh);
+ ocfs2_swap_xattr_entries_to_cpu(xh);
+ /*
+ * The real bucket num in this series of blocks is stored
+ * in the 1st bucket.
+ */
+ if (i == 0)
+ num_buckets = xh->xh_num_buckets;
+
+ ret = check_xattr(ost, di, xh, &changed);
+ if (ret)
+ break;
+ if (changed) {
+ ocfs2_swap_xattr_entries_from_cpu(xh);
+ ocfs2_swap_xattr_header(xh);
+ io_write_block(ost->ost_fs->fs_io, blkno,
+ blk_per_bucket, bucket);
+ }
+ }
+out:
+ if (bucket)
+ ocfs2_free(&bucket);
+
+ return ret;
+}
+
+static errcode_t o2fsck_check_xattr_index_block(o2fsck_state *ost,
+ struct ocfs2_dinode *di,
+ struct ocfs2_xattr_block *xb,
+ int *changed)
+{
+ struct ocfs2_extent_list *el = &xb->xb_attrs.xb_root.xt_list;
+ errcode_t ret = 0;
+ uint32_t name_hash = UINT_MAX, e_cpos = 0, num_clusters = 0;
+ uint64_t p_blkno = 0;
+ struct extent_info ei = {0, };
+
+ if (!el->l_next_free_rec)
+ return 0;
+
+ ret = check_el(ost, &ei, di, el,
+ ocfs2_extent_recs_per_xattr_block(ost->ost_fs->fs_blocksize),
+ changed);
+ if (ret)
+ return ret;
+
+ while (name_hash > 0) {
+ ret = ocfs2_xattr_get_rec(ost->ost_fs, xb, name_hash, &p_blkno,
+ &e_cpos, &num_clusters);
+ if (ret) {
+ com_err(whoami, ret, "while getting bucket record "
+ "of xattr data.");
+ goto out;
+ }
+
+ ret = ocfs2_check_xattr_buckets(ost, di, p_blkno,
+ num_clusters);
+ if (ret) {
+ com_err(whoami, ret, "while iterating buckets "
+ "of xattr data.");
+ goto out;
+ }
+
+ if (e_cpos == 0)
+ break;
+
+ name_hash = e_cpos - 1;
+ }
+
+out:
+ return ret;
+}
+
+static errcode_t o2fsck_check_xattr_block(o2fsck_state *ost,
+ struct ocfs2_dinode *di)
+{
+ errcode_t ret;
+ char *blk = NULL;
+ struct ocfs2_xattr_block *xb = NULL;
+ int changed = 0;
+
+ ret = ocfs2_malloc_block(ost->ost_fs->fs_io, &blk);
+ if (ret) {
+ com_err(whoami, ret, "while allocating room to read block "
+ "of xattr.");
+ return ret;
+ }
+
+ ret = ocfs2_read_xattr_block(ost->ost_fs, di->i_xattr_loc, blk);
+ if (ret) {
+ com_err(whoami, ret, "while reading externel block of xattr.");
+ return ret;
+ }
+
+ xb = (struct ocfs2_xattr_block *)blk;
+
+ if (!(xb->xb_flags & OCFS2_XATTR_INDEXED)) {
+ struct ocfs2_xattr_header *xh = &xb->xb_attrs.xb_header;
+
+ ret = check_xattr(ost, di, xh, &changed);
+ } else
+ ret = o2fsck_check_xattr_index_block(ost, di, xb, &changed);
+
+ if (changed)
+ ocfs2_write_xattr_block(ost->ost_fs, di->i_xattr_loc, blk);
+
+ if (blk)
+ ocfs2_free(&blk);
+
+ return ret;
+}
+
+static errcode_t o2fsck_check_xattr_ibody(o2fsck_state *ost,
+ struct ocfs2_dinode *di)
+{
+ errcode_t ret;
+ struct ocfs2_xattr_header *xh = NULL;
+ int changed = 0;
+
+ xh = (struct ocfs2_xattr_header *)
+ ((void *)di + ost->ost_fs->fs_blocksize -
+ di->i_xattr_inline_size);
+
+ ocfs2_swap_xattr_header(xh);
+ ocfs2_swap_xattr_entries_to_cpu(xh);
+
+ ret = check_xattr(ost, di, xh, &changed);
+
+ if (changed) {
+ ocfs2_swap_xattr_entries_from_cpu(xh);
+ ocfs2_swap_xattr_header(xh);
+ o2fsck_write_inode(ost, di->i_blkno, di);
+ }
+ return ret;
+}
+
+/*
+ * o2fsck_check_xattr
+ *
+ * Check extended attribute in inode block or external block.
+ */
+errcode_t o2fsck_check_xattr(o2fsck_state *ost,
+ struct ocfs2_dinode *di)
+{
+ errcode_t ret = 0;
+
+ if (!(di->i_dyn_features & OCFS2_HAS_XATTR_FL))
+ return 0;
+
+ if (di->i_dyn_features & OCFS2_INLINE_XATTR_FL)
+ ret = o2fsck_check_xattr_ibody(ost, di);
+
+ if (!ret && di->i_xattr_loc)
+ ret = o2fsck_check_xattr_block(ost, di);
+
+ return ret;
+}
--
1.5.4.1
More information about the Ocfs2-tools-devel
mailing list