osc copypac from project:network:ha-clustering package:ocfs2-tools revision:1

OBS-URL: https://build.opensuse.org/package/show/network:ha-clustering:Factory/ocfs2-tools?expand=0&rev=8
This commit is contained in:
Tim Serong 2010-06-25 12:23:00 +00:00 committed by Git OBS Bridge
parent 2553976dd6
commit c8700c5230
57 changed files with 8761 additions and 1623 deletions

View File

@ -0,0 +1,843 @@
From 1f8bab1217e89bd3f2e0bbd9934dd07fc24dff5d Mon Sep 17 00:00:00 2001
From: Mark Fasheh <mfasheh@suse.com>
Date: Sun, 11 Apr 2010 16:09:58 +0800
Subject: [PATCH 01/30] dx_dirs: Add library support for directory indexing
This patch updates ocs2_fs.h with the relevant directory indexing
structures. Additionally, libocfs2/ is given swap
functions for the new disk structures. The library also gets three new
iteration functions:
ocfs2_dx_entries_iterate() - to iterate all index entries in an inline,
or external index.
ocfs2_dx_frees_iterate() - an iterator for the dirblock free list.
ocfs2_extent_iterate_dx_root() - iterate the extent blocks of an index
tree.
Caveats:
Right now, this is all read-only. A major 'TODO' item is adding the
appropriate API's to enable creation, deletion and
various manipulation of the dx tree, as well as individual items.
None of the other library code really knows about the directory index.
This means that things like ocfs2_looup() is
still using the old-style lookup via the unindexed dirent tree.
We need to add support for the newly increased links_count maximum. This
should probably be a seperate patch though.
[modified the patch for code rebase and cleanup -- Coly Li]
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Signed-off-by: Coly Li <coly.li@suse.de>
---
include/ocfs2-kernel/ocfs2_fs.h | 129 +++++++++++++++++++++++++++++++-
include/ocfs2/ocfs2.h | 46 ++++++++++++
libocfs2/dir_iterate.c | 155 +++++++++++++++++++++++++++++++++++++++
libocfs2/dirblock.c | 140 +++++++++++++++++++++++++++++++++++-
libocfs2/extents.c | 89 ++++++++++++++++++++++
libocfs2/feature_string.c | 12 +++-
libocfs2/inode.c | 2 +
sizetest/sizes.txt | 2 +-
sizetest/sizetest.c | 3 +-
9 files changed, 570 insertions(+), 8 deletions(-)
diff --git a/include/ocfs2-kernel/ocfs2_fs.h b/include/ocfs2-kernel/ocfs2_fs.h
index 3fb0d6c..d4de181 100644
--- a/include/ocfs2-kernel/ocfs2_fs.h
+++ b/include/ocfs2-kernel/ocfs2_fs.h
@@ -67,6 +67,8 @@
#define OCFS2_XATTR_BLOCK_SIGNATURE "XATTR01"
#define OCFS2_DIR_TRAILER_SIGNATURE "DIRTRL1"
#define OCFS2_REFCOUNT_BLOCK_SIGNATURE "REFCNT1"
+#define OCFS2_DX_ROOT_SIGNATURE "DXDIR01"
+#define OCFS2_DX_LEAF_SIGNATURE "DXLEAF1"
/* Compatibility flags */
#define OCFS2_HAS_COMPAT_FEATURE(sb,mask) \
@@ -97,7 +99,8 @@
| OCFS2_FEATURE_INCOMPAT_USERSPACE_STACK \
| OCFS2_FEATURE_INCOMPAT_META_ECC \
| OCFS2_FEATURE_INCOMPAT_XATTR \
- | OCFS2_FEATURE_INCOMPAT_REFCOUNT_TREE)
+ | OCFS2_FEATURE_INCOMPAT_REFCOUNT_TREE \
+ | OCFS2_FEATURE_INCOMPAT_INDEXED_DIRS)
#define OCFS2_FEATURE_RO_COMPAT_SUPP (OCFS2_FEATURE_RO_COMPAT_UNWRITTEN \
| OCFS2_FEATURE_RO_COMPAT_USRQUOTA \
| OCFS2_FEATURE_RO_COMPAT_GRPQUOTA)
@@ -153,6 +156,9 @@
/* Support for extended attributes */
#define OCFS2_FEATURE_INCOMPAT_XATTR 0x0200
+/* Support for indexed directores */
+#define OCFS2_FEATURE_INCOMPAT_INDEXED_DIRS 0x0400
+
/* Metadata checksum and error correction */
#define OCFS2_FEATURE_INCOMPAT_META_ECC 0x0800
@@ -375,8 +381,11 @@ static struct ocfs2_system_inode_info ocfs2_system_inodes[NUM_SYSTEM_INODES] = {
#define OCFS2_DIR_REC_LEN(name_len) (((name_len) + OCFS2_DIR_MEMBER_LEN + \
OCFS2_DIR_ROUND) & \
~OCFS2_DIR_ROUND)
+#define OCFS2_DIR_MIN_REC_LEN OCFS2_DIR_REC_LEN(1)
#define OCFS2_LINK_MAX 32000
+#define OCFS2_DX_LINK_MAX ((1U << 31) - 1U)
+#define OCFS2_LINKS_HI_SHIFT 16
#define S_SHIFT 12
static unsigned char ocfs2_type_by_mode[S_IFMT >> S_SHIFT] = {
@@ -592,8 +601,9 @@ struct ocfs2_super_block {
/*B8*/ __le16 s_xattr_inline_size; /* extended attribute inline size
for this fs*/
__le16 s_reserved0;
- __le32 s_reserved1;
-/*C0*/ __le64 s_reserved2[16]; /* Fill out superblock */
+ __le32 s_dx_seed[3]; /* seed[0-2] for dx dir hash.
+ * s_uuid_hash serves as seed[3]. */
+/*C0*/ __le64 s_reserved2[15]; /* Fill out superblock */
/*140*/
/*
@@ -643,7 +653,7 @@ struct ocfs2_dinode {
belongs to */
__le16 i_suballoc_bit; /* Bit offset in suballocator
block group */
-/*10*/ __le16 i_reserved0;
+/*10*/ __le16 i_links_count_hi; /* High 16 bits of links count */
__le16 i_xattr_inline_size;
__le32 i_clusters; /* Cluster count */
__le32 i_uid; /* Owner UID */
@@ -747,6 +757,87 @@ struct ocfs2_dir_block_trailer {
/*40*/
};
+ /*
+ * A directory entry in the indexed tree. We don't store the full name here,
+ * but instead provide a pointer to the full dirent in the unindexed tree.
+ *
+ * We also store name_len here so as to reduce the number of leaf blocks we
+ * need to search in case of collisions.
+ */
+struct ocfs2_dx_entry {
+ __le32 dx_major_hash; /* Used to find logical
+ * cluster in index */
+ __le32 dx_minor_hash; /* Lower bits used to find
+ * block in cluster */
+ __le64 dx_dirent_blk; /* Physical block in unindexed
+ * tree holding this dirent. */
+};
+
+struct ocfs2_dx_entry_list {
+ __le32 de_reserved;
+ __le16 de_count; /* Maximum number of entries
+ * possible in de_entries */
+ __le16 de_num_used; /* Current number of
+ * de_entries entries */
+ struct ocfs2_dx_entry de_entries[0]; /* Indexed dir entries
+ * in a packed array of
+ * length de_num_used */
+};
+
+#define OCFS2_DX_FLAG_INLINE 0x01
+
+/*
+ * A directory indexing block. Each indexed directory has one of these,
+ * pointed to by ocfs2_dinode.
+ *
+ * This block stores an indexed btree root, and a set of free space
+ * start-of-list pointers.
+ */
+struct ocfs2_dx_root_block {
+ __u8 dr_signature[8]; /* Signature for verification */
+ struct ocfs2_block_check dr_check; /* Error checking */
+ __le16 dr_suballoc_slot; /* Slot suballocator this
+ * block belongs to. */
+ __le16 dr_suballoc_bit; /* Bit offset in suballocator
+ * block group */
+ __le32 dr_fs_generation; /* Must match super block */
+ __le64 dr_blkno; /* Offset on disk, in blocks */
+ __le64 dr_last_eb_blk; /* Pointer to last
+ * extent block */
+ __le32 dr_clusters; /* Clusters allocated
+ * to the indexed tree. */
+ __u8 dr_flags; /* OCFS2_DX_FLAG_* flags */
+ __u8 dr_reserved0;
+ __le16 dr_reserved1;
+ __le64 dr_dir_blkno; /* Pointer to parent inode */
+ __le64 dr_reserved2;
+ __le64 dr_free_blk; /* Pointer to head of free
+ * unindexed block list. */
+ __le64 dr_reserved3[15];
+ union {
+ struct ocfs2_extent_list dr_list; /* Keep this aligned to 128
+ * bits for maximum space
+ * efficiency. */
+ struct ocfs2_dx_entry_list dr_entries; /* In-root-block list of
+ * entries. We grow out
+ * to extents if this
+ * gets too big. */
+ };
+};
+
+/*
+ * The header of a leaf block in the indexed tree.
+ */
+struct ocfs2_dx_leaf {
+ __u8 dl_signature[8];/* Signature for verification */
+ struct ocfs2_block_check dl_check; /* Error checking */
+ __le64 dl_blkno; /* Offset on disk, in blocks */
+ __le32 dl_fs_generation;/* Must match super block */
+ __le32 dl_reserved0;
+ __le64 dl_reserved1;
+ struct ocfs2_dx_entry_list dl_list;
+};
+
/*
* On disk allocator group structure for OCFS2
*/
@@ -1133,6 +1224,16 @@ static inline int ocfs2_extent_recs_per_inode_with_xattr(
return size / sizeof(struct ocfs2_extent_rec);
}
+static inline int ocfs2_extent_recs_per_dx_root(struct super_block *sb)
+{
+ int size;
+
+ size = sb->s_blocksize -
+ offsetof(struct ocfs2_dx_root_block, dr_list.l_recs);
+
+ return size / sizeof(struct ocfs2_extent_rec);
+}
+
static inline int ocfs2_chain_recs_per_inode(struct super_block *sb)
{
int size;
@@ -1153,6 +1254,26 @@ static inline u16 ocfs2_extent_recs_per_eb(struct super_block *sb)
return size / sizeof(struct ocfs2_extent_rec);
}
+static inline int ocfs2_dx_entries_per_leaf(struct super_block *sb)
+{
+ int size;
+
+ size = sb->s_blocksize -
+ offsetof(struct ocfs2_dx_leaf, dl_list.de_entries);
+
+ return size / sizeof(struct ocfs2_dx_entry);
+}
+
+static inline int ocfs2_dx_entries_per_root(struct super_block *sb)
+{
+ int size;
+
+ size = sb->s_blocksize -
+ offsetof(struct ocfs2_dx_root_block, dr_entries.de_entries);
+
+ return size / sizeof(struct ocfs2_dx_entry);
+}
+
static inline u16 ocfs2_local_alloc_size(struct super_block *sb)
{
u16 size;
diff --git a/include/ocfs2/ocfs2.h b/include/ocfs2/ocfs2.h
index d91f734..332d4bd 100644
--- a/include/ocfs2/ocfs2.h
+++ b/include/ocfs2/ocfs2.h
@@ -473,6 +473,11 @@ int ocfs2_skip_dir_trailer(ocfs2_filesys *fs, struct ocfs2_dinode *di,
struct ocfs2_dir_entry *de, unsigned long offset);
void ocfs2_init_dir_trailer(ocfs2_filesys *fs, struct ocfs2_dinode *di,
uint64_t blkno, void *buf);
+errcode_t ocfs2_read_dx_root(ocfs2_filesys *fs, uint64_t block,
+ void *buf);
+errcode_t ocfs2_read_dx_leaf(ocfs2_filesys *fs, uint64_t block,
+ void *buf);
+int ocfs2_dir_indexed(struct ocfs2_dinode *di);
errcode_t ocfs2_dir_iterate2(ocfs2_filesys *fs,
uint64_t dir,
@@ -497,6 +502,27 @@ extern errcode_t ocfs2_dir_iterate(ocfs2_filesys *fs,
void *priv_data),
void *priv_data);
+extern errcode_t ocfs2_dx_entries_iterate(ocfs2_filesys *fs,
+ struct ocfs2_dinode *dir,
+ int flags,
+ int (*func)(ocfs2_filesys *fs,
+ struct ocfs2_dx_entry_list *entry_list,
+ struct ocfs2_dx_root_block *dx_root,
+ struct ocfs2_dx_leaf *dx_leaf,
+ void *priv_data),
+ void *priv_data);
+
+extern errcode_t ocfs2_dx_frees_iterate(ocfs2_filesys *fs,
+ struct ocfs2_dinode *dir,
+ struct ocfs2_dx_root_block *dx_root,
+ int flags,
+ int (*func)(ocfs2_filesys *fs,
+ uint64_t blkno,
+ struct ocfs2_dir_block_trailer *trailer,
+ char *dirblock,
+ void *priv_data),
+ void *priv_data);
+
errcode_t ocfs2_lookup(ocfs2_filesys *fs, uint64_t dir,
const char *name, int namelen, char *buf,
uint64_t *inode);
@@ -1224,6 +1250,13 @@ static inline int ocfs2_support_xattr(struct ocfs2_super_block *osb)
return 0;
}
+static inline int ocfs2_supports_indexed_dirs(struct ocfs2_super_block *osb)
+{
+ if (osb->s_feature_incompat & OCFS2_FEATURE_INCOMPAT_INDEXED_DIRS)
+ return 1;
+ return 0;
+}
+
/*
* When we're swapping some of our disk structures, a garbage count
* can send us past the edge of a block buffer. This function guards
@@ -1352,6 +1385,19 @@ errcode_t ocfs2_extent_iterate_inode(ocfs2_filesys *fs,
int ref_recno,
void *priv_data),
void *priv_data);
+errcode_t ocfs2_extent_iterate_dx_root(ocfs2_filesys *fs,
+ struct ocfs2_dx_root_block *dx_root,
+ int flags,
+ char *block_buf,
+ int (*func)(ocfs2_filesys *fs,
+ struct ocfs2_extent_rec *rec,
+ int tree_depth,
+ uint32_t ccount,
+ uint64_t ref_blkno,
+ int ref_recno,
+ void *priv_data),
+ void *priv_data);
+
errcode_t ocfs2_block_iterate(ocfs2_filesys *fs,
uint64_t blkno,
int flags,
diff --git a/libocfs2/dir_iterate.c b/libocfs2/dir_iterate.c
index 00c8d16..1064d9f 100644
--- a/libocfs2/dir_iterate.c
+++ b/libocfs2/dir_iterate.c
@@ -307,6 +307,161 @@ int ocfs2_process_dir_block(ocfs2_filesys *fs,
return 0;
}
+struct dx_iterator_data {
+ int (*dx_func)(ocfs2_filesys *fs,
+ struct ocfs2_dx_entry_list *entry_list,
+ struct ocfs2_dx_root_block *dx_root,
+ struct ocfs2_dx_leaf *dx_leaf,
+ void *priv_data);
+ void *dx_priv_data;
+ char *leaf_buf;
+ struct ocfs2_dx_root_block *dx_root;
+};
+
+static int dx_iterator(ocfs2_filesys *fs,
+ struct ocfs2_extent_rec *rec,
+ int tree_depth,
+ uint32_t ccount,
+ uint64_t ref_blkno,
+ int ref_recno,
+ void *priv_data)
+{
+ int ret, i;
+ struct ocfs2_dx_leaf *dx_leaf;
+ struct dx_iterator_data *iter = priv_data;
+ uint64_t blkno, count;
+
+ count = ocfs2_clusters_to_blocks(fs, rec->e_leaf_clusters);
+
+ blkno = rec->e_blkno;
+ for (i = 0; i < count; i++) {
+ ret = ocfs2_read_dx_leaf(fs, blkno, iter->leaf_buf);
+ if (ret)
+ return ret;
+
+ dx_leaf = (struct ocfs2_dx_leaf *)iter->leaf_buf;
+ iter->dx_func(fs, &dx_leaf->dl_list, iter->dx_root, dx_leaf,
+ iter->dx_priv_data);
+
+ blkno++;
+ }
+
+ return 0;
+}
+
+extern errcode_t ocfs2_dx_entries_iterate(ocfs2_filesys *fs,
+ struct ocfs2_dinode *dir,
+ int flags,
+ int (*func)(ocfs2_filesys *fs,
+ struct ocfs2_dx_entry_list *entry_list,
+ struct ocfs2_dx_root_block *dx_root,
+ struct ocfs2_dx_leaf *dx_leaf,
+ void *priv_data),
+ void *priv_data)
+{
+ errcode_t ret = 0;
+ struct ocfs2_dx_root_block *dx_root;
+ uint64_t dx_blkno;
+ char *buf = NULL, *eb_buf = NULL, *leaf_buf = NULL;
+ struct dx_iterator_data data;
+
+ if (!S_ISDIR(dir->i_mode) && !ocfs2_dir_indexed(dir)) {
+ ret = 0;
+ goto out;
+ }
+
+ ret = ocfs2_malloc_block(fs->fs_io, &buf);
+ if (ret)
+ goto out;
+
+ dx_blkno = (uint64_t) dir->i_dx_root;
+
+ ret = ocfs2_read_dx_root(fs, dx_blkno, buf);
+ if (ret)
+ goto out;
+
+ dx_root = (struct ocfs2_dx_root_block *)buf;
+
+ if (dx_root->dr_flags & OCFS2_DX_FLAG_INLINE) {
+ func(fs, &dx_root->dr_entries, dx_root, NULL, priv_data);
+ ret = 0;
+ goto out;
+ }
+
+ ret = ocfs2_malloc_block(fs->fs_io, &eb_buf);
+ if (ret)
+ goto out;
+
+ ret = ocfs2_malloc_block(fs->fs_io, &leaf_buf);
+ if (ret)
+ goto out;
+
+ data.dx_func = func;
+ data.dx_priv_data = priv_data;
+ data.leaf_buf = leaf_buf;
+ data.dx_root = dx_root;
+ ret = ocfs2_extent_iterate_dx_root(fs, dx_root,
+ OCFS2_EXTENT_FLAG_DATA_ONLY, eb_buf,
+ dx_iterator, &data);
+
+out:
+ if (buf)
+ ocfs2_free(&buf);
+ if (eb_buf)
+ ocfs2_free(&eb_buf);
+ if (leaf_buf)
+ ocfs2_free(&leaf_buf);
+ return ret;
+}
+
+extern errcode_t ocfs2_dx_frees_iterate(ocfs2_filesys *fs,
+ struct ocfs2_dinode *dir,
+ struct ocfs2_dx_root_block *dx_root,
+ int flags,
+ int (*func)(ocfs2_filesys *fs,
+ uint64_t blkno,
+ struct ocfs2_dir_block_trailer *trailer,
+ char *dirblock,
+ void *priv_data),
+ void *priv_data)
+{
+ errcode_t ret = 0;
+ uint64_t blkno;
+ char *buf = NULL;
+ struct ocfs2_dir_block_trailer *trailer;
+
+ if (!S_ISDIR(dir->i_mode) || !(ocfs2_dir_indexed(dir))) {
+ ret = 0;
+ goto out;
+ }
+
+ if (dx_root->dr_flags & OCFS2_DX_FLAG_INLINE) {
+ ret = 0;
+ goto out;
+ }
+
+ ret = ocfs2_malloc_block(fs->fs_io, &buf);
+ if (ret)
+ goto out;
+
+ blkno = dx_root->dr_free_blk;
+ while (blkno) {
+ ret = ocfs2_read_dir_block(fs, dir, blkno, buf);
+ if (ret)
+ goto out;
+
+ trailer = ocfs2_dir_trailer_from_block(fs, buf);
+
+ func(fs, blkno, trailer, buf, priv_data);
+
+ blkno = trailer->db_free_next;
+ }
+
+out:
+ if (buf)
+ ocfs2_free(&buf);
+ return ret;
+}
#ifdef DEBUG_EXE
#include <stdlib.h>
diff --git a/libocfs2/dirblock.c b/libocfs2/dirblock.c
index fec8ffc..d68e5c0 100644
--- a/libocfs2/dirblock.c
+++ b/libocfs2/dirblock.c
@@ -54,12 +54,17 @@ int ocfs2_dir_has_trailer(ocfs2_filesys *fs, struct ocfs2_dinode *di)
(di->i_dyn_features & OCFS2_INLINE_DATA_FL))
return 0;
+ if (ocfs2_supports_indexed_dirs(OCFS2_RAW_SB(fs->fs_super)) &&
+ di->i_dyn_features & OCFS2_INDEXED_DIR_FL)
+ return 1;
+
return ocfs2_meta_ecc(OCFS2_RAW_SB(fs->fs_super));
}
int ocfs2_supports_dir_trailer(ocfs2_filesys *fs)
{
- return ocfs2_meta_ecc(OCFS2_RAW_SB(fs->fs_super));
+ return ocfs2_meta_ecc(OCFS2_RAW_SB(fs->fs_super)) ||
+ ocfs2_supports_indexed_dirs(OCFS2_RAW_SB(fs->fs_super));
}
int ocfs2_skip_dir_trailer(ocfs2_filesys *fs, struct ocfs2_dinode *di,
@@ -148,6 +153,8 @@ void ocfs2_swap_dir_trailer(struct ocfs2_dir_block_trailer *trailer)
bswap_64(trailer->db_compat_rec_len);
bswap_64(trailer->db_blkno);
bswap_64(trailer->db_parent_dinode);
+ bswap_16(trailer->db_free_rec_len);
+ bswap_64(trailer->db_free_next);
}
errcode_t ocfs2_read_dir_block(ocfs2_filesys *fs, struct ocfs2_dinode *di,
@@ -222,3 +229,134 @@ out:
ocfs2_free(&buf);
return retval;
}
+
+static void ocfs2_swap_dx_entry_to_cpu(struct ocfs2_dx_entry *dx_entry)
+{
+ if (cpu_is_little_endian)
+ return;
+
+ dx_entry->dx_major_hash = bswap_32(dx_entry->dx_major_hash);
+ dx_entry->dx_minor_hash = bswap_32(dx_entry->dx_minor_hash);
+ dx_entry->dx_dirent_blk = bswap_64(dx_entry->dx_dirent_blk);
+}
+
+static void ocfs2_swap_dx_entry_list_to_cpu(struct ocfs2_dx_entry_list *dl_list)
+{
+ int i;
+
+ if (cpu_is_little_endian)
+ return;
+
+ dl_list->de_count = bswap_16(dl_list->de_count);
+ dl_list->de_num_used = bswap_16(dl_list->de_num_used);
+
+ for (i = 0; i < dl_list->de_count; i++)
+ ocfs2_swap_dx_entry_to_cpu(&dl_list->de_entries[i]);
+}
+
+static void ocfs2_swap_dx_root_to_cpu(struct ocfs2_dx_root_block *dx_root)
+{
+ if (cpu_is_little_endian)
+ return;
+
+ dx_root->dr_suballoc_slot = bswap_16(dx_root->dr_suballoc_slot);
+ dx_root->dr_suballoc_bit = bswap_16(dx_root->dr_suballoc_bit);
+ dx_root->dr_fs_generation = bswap_32(dx_root->dr_fs_generation);
+ dx_root->dr_blkno = bswap_64(dx_root->dr_blkno);
+ dx_root->dr_last_eb_blk = bswap_64(dx_root->dr_last_eb_blk);
+ dx_root->dr_clusters = bswap_32(dx_root->dr_clusters);
+ dx_root->dr_dir_blkno = bswap_64(dx_root->dr_dir_blkno);
+ dx_root->dr_free_blk = bswap_64(dx_root->dr_free_blk);
+
+ if (dx_root->dr_flags & OCFS2_DX_FLAG_INLINE)
+ ocfs2_swap_dx_entry_list_to_cpu(&dx_root->dr_entries);
+ else
+ ocfs2_swap_extent_list_to_cpu(&dx_root->dr_list);
+}
+
+errcode_t ocfs2_read_dx_root(ocfs2_filesys *fs, uint64_t block,
+ void *buf)
+{
+ errcode_t ret;
+ struct ocfs2_dx_root_block *dx_root;
+
+ ret = ocfs2_read_blocks(fs, block, 1, buf);
+ if (ret)
+ return ret;
+
+ dx_root = (struct ocfs2_dx_root_block *)buf;
+ ret = ocfs2_validate_meta_ecc(fs, buf, &dx_root->dr_check);
+ if (ret)
+ return ret;
+
+ if (memcmp(dx_root->dr_signature, OCFS2_DX_ROOT_SIGNATURE,
+ strlen(OCFS2_DX_ROOT_SIGNATURE)))
+ return OCFS2_ET_DIR_CORRUPTED;
+
+ ocfs2_swap_dx_root_to_cpu(dx_root);
+
+ return 0;
+}
+
+static void ocfs2_swap_dx_leaf_to_cpu(struct ocfs2_dx_leaf *dx_leaf)
+{
+ if (cpu_is_little_endian)
+ return;
+
+ dx_leaf->dl_blkno = bswap_64(dx_leaf->dl_blkno);
+ dx_leaf->dl_fs_generation = bswap_64(dx_leaf->dl_fs_generation);
+
+ ocfs2_swap_dx_entry_list_to_cpu(&dx_leaf->dl_list);
+}
+
+errcode_t ocfs2_read_dx_leaf(ocfs2_filesys *fs, uint64_t block,
+ void *buf)
+{
+ errcode_t ret;
+ struct ocfs2_dx_leaf *dx_leaf;
+
+ ret = ocfs2_read_blocks(fs, block, 1, buf);
+ if (ret)
+ return ret;
+
+ dx_leaf = (struct ocfs2_dx_leaf *)buf;
+ ret = ocfs2_validate_meta_ecc(fs, buf, &dx_leaf->dl_check);
+ if (ret)
+ return ret;
+
+ if (memcmp(dx_leaf->dl_signature, OCFS2_DX_LEAF_SIGNATURE,
+ strlen(OCFS2_DX_LEAF_SIGNATURE)))
+ return OCFS2_ET_DIR_CORRUPTED;
+
+ ocfs2_swap_dx_leaf_to_cpu(dx_leaf);
+
+ return 0;
+}
+
+int ocfs2_dir_indexed(struct ocfs2_dinode *di)
+{
+ if (di->i_dyn_features & OCFS2_INDEXED_DIR_FL)
+ return 1;
+ return 0;
+}
+
+/*
+ * Only use this when we already know the directory is indexed.
+ */
+int __ocfs2_is_dir_trailer(ocfs2_filesys *fs, unsigned long de_off)
+{
+ if (de_off == ocfs2_dir_trailer_blk_off(fs))
+ return 1;
+
+ return 0;
+}
+
+int ocfs2_is_dir_trailer(ocfs2_filesys *fs, struct ocfs2_dinode *di,
+ unsigned long de_off)
+{
+ if (ocfs2_dir_has_trailer(fs, di)) {
+ return __ocfs2_is_dir_trailer(fs, de_off);
+ }
+
+ return 0;
+}
diff --git a/libocfs2/extents.c b/libocfs2/extents.c
index ee7ef93..8c322b1 100644
--- a/libocfs2/extents.c
+++ b/libocfs2/extents.c
@@ -550,6 +550,95 @@ out:
return ret;
}
+errcode_t ocfs2_extent_iterate_dx_root(ocfs2_filesys *fs,
+ struct ocfs2_dx_root_block *dx_root,
+ int flags,
+ char *block_buf,
+ int (*func)(ocfs2_filesys *fs,
+ struct ocfs2_extent_rec *rec,
+ int tree_depth,
+ uint32_t ccount,
+ uint64_t ref_blkno,
+ int ref_recno,
+ void *priv_data),
+ void *priv_data)
+{
+ int i;
+ int iret = 0;
+ struct ocfs2_extent_list *el;
+ errcode_t ret;
+ struct extent_context ctxt;
+
+ if (dx_root->dr_flags & OCFS2_DX_FLAG_INLINE)
+ return OCFS2_ET_INODE_CANNOT_BE_ITERATED;
+
+ el = &dx_root->dr_list;
+ if (el->l_tree_depth) {
+ ret = ocfs2_malloc0(sizeof(char *) * el->l_tree_depth,
+ &ctxt.eb_bufs);
+ if (ret)
+ goto out;
+
+ if (block_buf) {
+ ctxt.eb_bufs[0] = block_buf;
+ } else {
+ ret = ocfs2_malloc0(fs->fs_blocksize *
+ el->l_tree_depth,
+ &ctxt.eb_bufs[0]);
+ if (ret)
+ goto out_eb_bufs;
+ }
+
+ for (i = 1; i < el->l_tree_depth; i++) {
+ ctxt.eb_bufs[i] = ctxt.eb_bufs[0] +
+ i * fs->fs_blocksize;
+ }
+ }
+ else
+ ctxt.eb_bufs = NULL;
+
+ ctxt.fs = fs;
+ ctxt.func = func;
+ ctxt.priv_data = priv_data;
+ ctxt.flags = flags;
+ ctxt.ccount = 0;
+ ctxt.last_eb_blkno = 0;
+ ctxt.last_eb_cpos = 0;
+
+ ret = 0;
+ iret |= extent_iterate_el(el, 0, &ctxt);
+ if (iret & OCFS2_EXTENT_ERROR)
+ ret = ctxt.errcode;
+
+ if (iret & OCFS2_EXTENT_ABORT)
+ goto out_abort;
+
+ /* we can only trust ctxt.last_eb_blkno if we walked the whole tree */
+ if (dx_root->dr_last_eb_blk != ctxt.last_eb_blkno) {
+ dx_root->dr_last_eb_blk = ctxt.last_eb_blkno;
+ iret |= OCFS2_EXTENT_CHANGED;
+ }
+
+out_abort:
+#if 0
+ /*
+ * This block needs to be fixed up for write support.
+ */
+ if (!ret && (iret & OCFS2_EXTENT_CHANGED))
+ ret = ocfs2_write_inode(fs, inode->i_blkno, (char *)inode);
+#endif
+
+out_eb_bufs:
+ if (ctxt.eb_bufs) {
+ if (!block_buf && ctxt.eb_bufs[0])
+ ocfs2_free(&ctxt.eb_bufs[0]);
+ ocfs2_free(&ctxt.eb_bufs);
+ }
+
+out:
+ return ret;
+}
+
errcode_t ocfs2_extent_iterate(ocfs2_filesys *fs,
uint64_t blkno,
int flags,
diff --git a/libocfs2/feature_string.c b/libocfs2/feature_string.c
index 7021dba..9f395c6 100644
--- a/libocfs2/feature_string.c
+++ b/libocfs2/feature_string.c
@@ -89,7 +89,8 @@ static ocfs2_fs_options feature_level_defaults[] = {
OCFS2_FEATURE_INCOMPAT_INLINE_DATA |
OCFS2_FEATURE_INCOMPAT_META_ECC |
OCFS2_FEATURE_INCOMPAT_XATTR |
- OCFS2_FEATURE_INCOMPAT_REFCOUNT_TREE,
+ OCFS2_FEATURE_INCOMPAT_REFCOUNT_TREE |
+ OCFS2_FEATURE_INCOMPAT_INDEXED_DIRS,
OCFS2_FEATURE_RO_COMPAT_UNWRITTEN |
OCFS2_FEATURE_RO_COMPAT_USRQUOTA |
OCFS2_FEATURE_RO_COMPAT_GRPQUOTA }, /* OCFS2_FEATURE_LEVEL_MAX_FEATURES */
@@ -166,6 +167,11 @@ static struct fs_feature_flags ocfs2_supported_features[] = {
{0, OCFS2_FEATURE_INCOMPAT_XATTR, 0},
},
{
+ "indexed-dirs",
+ {0, OCFS2_FEATURE_INCOMPAT_INDEXED_DIRS, 0},
+ {0, OCFS2_FEATURE_INCOMPAT_INDEXED_DIRS, 0},
+ },
+ {
"usrquota",
{0, 0, OCFS2_FEATURE_RO_COMPAT_USRQUOTA},
{0, 0, OCFS2_FEATURE_RO_COMPAT_USRQUOTA},
@@ -248,6 +254,10 @@ static struct feature_name ocfs2_feature_names[] = {
.fn_flag = {0, OCFS2_FEATURE_INCOMPAT_XATTR, 0},
},
{
+ .fn_name = "IndexedDirs",
+ .fn_flag = {0, OCFS2_FEATURE_INCOMPAT_INDEXED_DIRS, 0},
+ },
+ {
.fn_name = "usrquota",
.fn_flag = {0, 0, OCFS2_FEATURE_RO_COMPAT_USRQUOTA},
},
diff --git a/libocfs2/inode.c b/libocfs2/inode.c
index e9ce579..95419f4 100644
--- a/libocfs2/inode.c
+++ b/libocfs2/inode.c
@@ -163,6 +163,8 @@ static void ocfs2_swap_inode_second(struct ocfs2_dinode *di)
struct ocfs2_inline_data *id = &di->id2.i_data;
id->id_count = bswap_16(id->id_count);
+ } else if (di->i_dyn_features & OCFS2_INDEXED_DIR_FL) {
+ di->i_dx_root = bswap_64(di->i_dx_root);
}
}
diff --git a/sizetest/sizes.txt b/sizetest/sizes.txt
index d03b67c..1fb27a9 100644
--- a/sizetest/sizes.txt
+++ b/sizetest/sizes.txt
@@ -110,7 +110,7 @@
0x0C0 id2.i_chain +0x10
0x0C0 id2.i_list +0x10
0x0C0 id2.i_symlink +0x00
- Total 0x200
+ Total 0x208
[off] struct ocfs2_dir_entry [size]
0x000 inode +0x08
diff --git a/sizetest/sizetest.c b/sizetest/sizetest.c
index bdb06a2..e01e800 100644
--- a/sizetest/sizetest.c
+++ b/sizetest/sizetest.c
@@ -173,7 +173,7 @@ static void print_ocfs2_dinode(void)
SHOW_OFFSET(struct ocfs2_dinode, i_generation);
SHOW_OFFSET(struct ocfs2_dinode, i_suballoc_slot);
SHOW_OFFSET(struct ocfs2_dinode, i_suballoc_bit);
- SHOW_OFFSET(struct ocfs2_dinode, i_reserved0);
+ SHOW_OFFSET(struct ocfs2_dinode, i_links_count_hi);
SHOW_OFFSET(struct ocfs2_dinode, i_xattr_inline_size);
SHOW_OFFSET(struct ocfs2_dinode, i_clusters);
SHOW_OFFSET(struct ocfs2_dinode, i_uid);
@@ -197,6 +197,7 @@ static void print_ocfs2_dinode(void)
SHOW_OFFSET(struct ocfs2_dinode, i_dyn_features);
SHOW_OFFSET(struct ocfs2_dinode, i_xattr_loc);
SHOW_OFFSET(struct ocfs2_dinode, i_check);
+ SHOW_OFFSET(struct ocfs2_dinode, i_dx_root);
SHOW_OFFSET(struct ocfs2_dinode, i_reserved2);
SHOW_OFFSET(struct ocfs2_dinode, id1.i_pad1);
--
1.7.0.2

View File

@ -0,0 +1,454 @@
From b891260ad1500f3f2c0562d4376307b18bc4a9f4 Mon Sep 17 00:00:00 2001
From: Mark Fasheh <mfasheh@suse.com>
Date: Sun, 11 Apr 2010 16:09:59 +0800
Subject: [PATCH 02/30] dx_dirs: debugfs.ocfs2 support
This adds a full set of functionality to debugfs.ocfs2 so that we can
visualize and debug indexed directories. Aside
from updates to other commands to dump newly added/used fields in old
structures, we get the following debugfs.ocfs2 commands:
dx_space - Show all entries in the free list
dx_dump - Show the directory index (including root block)
dx_leaf - Show a single directory index leaf block
dx_root - Show directory index root block, as well as any extent blocks
for non-inline dx_roots.
[modified the patch for code rebase and cleanup -- Coly Li]
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Signed-off-by: Coly Li <coly.li@suse.de>
---
debugfs.ocfs2/commands.c | 173 ++++++++++++++++++++++++++++++++++++++++++
debugfs.ocfs2/dump.c | 164 ++++++++++++++++++++++++++++++++++++++--
debugfs.ocfs2/include/dump.h | 5 +
3 files changed, 335 insertions(+), 7 deletions(-)
diff --git a/debugfs.ocfs2/commands.c b/debugfs.ocfs2/commands.c
index 1c19ab4..04e56b4 100644
--- a/debugfs.ocfs2/commands.c
+++ b/debugfs.ocfs2/commands.c
@@ -77,6 +77,10 @@ static void do_dirblocks(char **args);
static void do_xattr(char **args);
static void do_frag(char **args);
static void do_refcount(char **args);
+static void do_dx_root(char **args);
+static void do_dx_leaf(char **args);
+static void do_dx_dump(char **args);
+static void do_dx_space(char **args);
dbgfs_gbls gbls;
@@ -116,6 +120,10 @@ static Command commands[] = {
{ "dirblocks", do_dirblocks },
{ "frag", do_frag },
{ "refcount", do_refcount },
+ { "dx_root", do_dx_root },
+ { "dx_leaf", do_dx_leaf },
+ { "dx_dump", do_dx_dump },
+ { "dx_space", do_dx_space },
};
/*
@@ -842,6 +850,10 @@ static void do_help (char **args)
printf ("dlm_locks [-f <file>] [-l] lockname\t\t\tShow live dlm locking state\n");
printf ("dump [-p] <filespec> <outfile>\t\tDumps file to outfile on a mounted fs\n");
printf ("dirblocks <filespec>\t\t\tDump directory blocks\n");
+ printf ("dx_space <filespec>\t\t\tDump directory free space list\n");
+ printf ("dx_dump <blkno>\t\t\tShow directory index information\n");
+ printf ("dx_leaf <blkno>\t\t\tShow directory index leaf block only\n");
+ printf ("dx_root <blkno>\t\t\tShow directory index root block only\n");
printf ("encode <filespec>\t\t\tShow lock name\n");
printf ("extent <block#>\t\t\t\tShow extent block\n");
printf ("findpath <block#>\t\t\tList one pathname of the inode/lockname\n");
@@ -1316,6 +1328,167 @@ static void do_dirblocks (char **args)
}
/*
+ * do_dx_root()
+ *
+ */
+static void do_dx_root (char **args)
+{
+ struct ocfs2_dx_root_block *dx_root;
+ uint64_t blkno;
+ char *buf = NULL;
+ FILE *out;
+ errcode_t ret = 0;
+
+ if (process_inodestr_args(args, 1, &blkno) != 1)
+ return;
+
+ buf = gbls.blockbuf;
+ out = open_pager(gbls.interactive);
+
+ ret = ocfs2_read_dx_root(gbls.fs, blkno, buf);
+ if (ret) {
+ com_err(args[0], ret, "while reading dx dir root "
+ "block %"PRIu64"", blkno);
+ close_pager (out);
+ return;
+ }
+
+ dx_root = (struct ocfs2_dx_root_block *)buf;
+ dump_dx_root(out, dx_root);
+ if (!(dx_root->dr_flags & OCFS2_DX_FLAG_INLINE))
+ traverse_extents(gbls.fs, &dx_root->dr_list, out);
+ close_pager(out);
+
+ return;
+}
+
+/*
+ * do_dx_leaf()
+ *
+ */
+static void do_dx_leaf (char **args)
+{
+ struct ocfs2_dx_leaf *dx_leaf;
+ uint64_t blkno;
+ char *buf = NULL;
+ FILE *out;
+ errcode_t ret = 0;
+
+ if (process_inodestr_args(args, 1, &blkno) != 1)
+ return;
+
+ buf = gbls.blockbuf;
+ out = open_pager(gbls.interactive);
+
+ ret = ocfs2_read_dx_leaf(gbls.fs, blkno, buf);
+ if (ret) {
+ com_err(args[0], ret, "while reading dx dir leaf "
+ "block %"PRIu64"", blkno);
+ close_pager (out);
+ return;
+ }
+
+ dx_leaf = (struct ocfs2_dx_leaf *)buf;
+ dump_dx_leaf(out, dx_leaf);
+
+ close_pager(out);
+
+ return;
+}
+
+/*
+ * do_dx_dump()
+ *
+ */
+static void do_dx_dump (char **args)
+{
+ struct ocfs2_dinode *inode;
+ uint64_t ino_blkno;
+ char *buf = NULL;
+ FILE *out;
+ errcode_t ret = 0;
+
+ if (process_inode_args(args, &ino_blkno))
+ return;
+
+ out = open_pager(gbls.interactive);
+
+ buf = gbls.blockbuf;
+ ret = ocfs2_read_inode(gbls.fs, ino_blkno, buf);
+ if (ret) {
+ com_err(args[0], ret, "while reading inode %"PRIu64"",
+ ino_blkno);
+ close_pager (out);
+ return ;
+ }
+
+ inode = (struct ocfs2_dinode *)buf;
+
+ dump_dx_entries(out, inode);
+
+ close_pager(out);
+
+ return;
+}
+
+/*
+ * do_dx_space()
+ *
+ */
+static void do_dx_space (char **args)
+{
+ struct ocfs2_dinode *inode;
+ struct ocfs2_dx_root_block *dx_root;
+ uint64_t ino_blkno, dx_blkno;
+ char *buf = NULL, *dx_root_buf = NULL;
+ FILE *out;
+ errcode_t ret = 0;
+
+ if (process_inode_args(args, &ino_blkno))
+ return;
+
+ out = open_pager(gbls.interactive);
+
+ buf = gbls.blockbuf;
+ ret = ocfs2_read_inode(gbls.fs, ino_blkno, buf);
+ if (ret) {
+ com_err(args[0], ret, "while reading inode %"PRIu64"",
+ ino_blkno);
+ goto out;
+ }
+
+ inode = (struct ocfs2_dinode *)buf;
+ if (!(ocfs2_dir_indexed(inode))) {
+ fprintf(out, "Inode %"PRIu64" is not indexed\n", ino_blkno);
+ goto out;
+ }
+
+ ret = ocfs2_malloc_block(gbls.fs->fs_io, &dx_root_buf);
+ if (ret) {
+ goto out;
+ }
+
+ dx_blkno = (uint64_t) inode->i_dx_root;
+
+ ret = ocfs2_read_dx_root(gbls.fs, dx_blkno, dx_root_buf);
+ if (ret) {
+ com_err(args[0], ret, "while reading dx dir root "
+ "block %"PRIu64"", dx_blkno);
+ goto out;
+ }
+
+ dx_root = (struct ocfs2_dx_root_block *)dx_root_buf;
+
+ dump_dx_space(out, inode, dx_root);
+out:
+ close_pager(out);
+ if (dx_root_buf)
+ ocfs2_free(&dx_root_buf);
+
+ return;
+}
+
+/*
* do_extent()
*
*/
diff --git a/debugfs.ocfs2/dump.c b/debugfs.ocfs2/dump.c
index 7880991..2e887ce 100644
--- a/debugfs.ocfs2/dump.c
+++ b/debugfs.ocfs2/dump.c
@@ -99,6 +99,9 @@ void dump_super_block(FILE *out, struct ocfs2_super_block *sb)
fprintf(out, "%02X", sb->s_uuid[i]);
fprintf(out, "\n");
fprintf(out, "\tHash: %u (0x%x)\n", sb->s_uuid_hash, sb->s_uuid_hash);
+ for (i = 0; i < 3; i++)
+ fprintf(out, "\tDX Seed[%d]: 0x%08x\n", i, sb->s_dx_seed[i]);
+
if (ocfs2_userspace_stack(sb))
fprintf(out,
"\tCluster stack: %s\n"
@@ -315,6 +318,9 @@ void dump_inode(FILE *out, struct ocfs2_dinode *in)
if (in->i_dyn_features & OCFS2_INLINE_DATA_FL) {
fprintf(out, "\tInline Data Max: %u\n",
in->id2.i_data.id_count);
+ } else if (in->i_dyn_features & OCFS2_INDEXED_DIR_FL) {
+ fprintf(out, "\tIndexed Tree Root: %"PRIu64"\n",
+ (uint64_t)in->i_dx_root);
}
if (flags)
@@ -490,6 +496,21 @@ int dump_dir_entry (struct ocfs2_dir_entry *rec, int offset, int blocksize,
}
/*
+ * dump_dir_trailer()
+ */
+static void dump_dir_trailer(FILE *out, struct ocfs2_dir_block_trailer *trailer)
+{
+ fprintf(out,
+ "\tTrailer Block: %-15"PRIu64" Inode: %-15"PRIu64" rec_len: %-4u\n",
+ trailer->db_blkno, trailer->db_parent_dinode,
+ trailer->db_compat_rec_len);
+ fprintf(out,
+ "\tLargest hole: %u Next in list: %-15"PRIu64"\n",
+ trailer->db_free_rec_len, trailer->db_free_next);
+ dump_block_check(out, &trailer->db_check);
+}
+
+/*
* dump_dir_block()
*
*/
@@ -507,13 +528,9 @@ void dump_dir_block(FILE *out, char *buf)
};
if (!strncmp((char *)trailer->db_signature, OCFS2_DIR_TRAILER_SIGNATURE,
- sizeof(trailer->db_signature))) {
- fprintf(out,
- "\tTrailer Block: %-15"PRIu64" Inode: %-15"PRIu64" rec_len: %-4u\n",
- trailer->db_blkno, trailer->db_parent_dinode,
- trailer->db_compat_rec_len);
- dump_block_check(out, &trailer->db_check);
- } else
+ sizeof(trailer->db_signature)))
+ dump_dir_trailer(out, trailer);
+ else
end = gbls.fs->fs_blocksize;
fprintf(out, "\tEntries:\n");
@@ -533,6 +550,139 @@ void dump_dir_block(FILE *out, char *buf)
}
}
+static void dump_dx_entry(FILE *out, int i, struct ocfs2_dx_entry *dx_entry)
+{
+ fprintf(out, "\t %-2d (0x%08x 0x%08x) %-13"PRIu64"\n",
+ i, dx_entry->dx_major_hash, dx_entry->dx_minor_hash,
+ (uint64_t)dx_entry->dx_dirent_blk);
+}
+
+static void dump_dx_entry_list(FILE *out, struct ocfs2_dx_entry_list *dl_list,
+ int traverse)
+{
+ int i;
+
+ fprintf(out, "\tCount: %u Num Used: %u\n",
+ dl_list->de_count, dl_list->de_num_used);
+
+ if (traverse) {
+ fprintf(out, "\t## %-11s %-13s\n", "Hash (Major Minor)",
+ "Dir Block#");
+
+ for (i = 0; i < dl_list->de_num_used; i++)
+ dump_dx_entry(out, i, &dl_list->de_entries[i]);
+ }
+}
+
+void dump_dx_root(FILE *out, struct ocfs2_dx_root_block *dr)
+{
+ char tmp_str[30];
+ GString *flags = NULL;
+
+ flags = g_string_new(NULL);
+ if (dr->dr_flags & OCFS2_DX_FLAG_INLINE)
+ g_string_append(flags, "Inline ");
+
+ fprintf(out, "\tDir Index Root: %"PRIu64" FS Generation: %u (0x%x)\n",
+ (uint64_t)dr->dr_blkno, dr->dr_fs_generation,
+ dr->dr_fs_generation);
+
+ fprintf(out, "\tClusters: %u Last Extblk: %"PRIu64" "
+ "Dir Inode: %"PRIu64"\n",
+ dr->dr_clusters, (uint64_t)dr->dr_last_eb_blk,
+ (uint64_t)dr->dr_dir_blkno);
+
+ if (dr->dr_suballoc_slot == (uint16_t)OCFS2_INVALID_SLOT)
+ strcpy(tmp_str, "Global");
+ else
+ sprintf(tmp_str, "%d", dr->dr_suballoc_slot);
+ fprintf(out, "\tSub Alloc Slot: %s Sub Alloc Bit: %u "
+ "Flags: (0x%x) %s\n",
+ tmp_str, dr->dr_suballoc_bit, dr->dr_flags, flags->str);
+
+ dump_block_check(out, &dr->dr_check);
+
+ if (dr->dr_flags & OCFS2_DX_FLAG_INLINE)
+ dump_dx_entry_list(out, &dr->dr_entries, 0);
+
+ if (flags)
+ g_string_free(flags, 1);
+}
+
+void dump_dx_leaf (FILE *out, struct ocfs2_dx_leaf *dx_leaf)
+{
+ fprintf(out, "\tDir Index Leaf: %"PRIu64" FS Generation: %u (0x%x)\n",
+ (uint64_t)dx_leaf->dl_blkno, dx_leaf->dl_fs_generation,
+ dx_leaf->dl_fs_generation);
+ dump_block_check(out, &dx_leaf->dl_check);
+
+ dump_dx_entry_list(out, &dx_leaf->dl_list, 1);
+}
+
+static int entries_iter(ocfs2_filesys *fs,
+ struct ocfs2_dx_entry_list *entry_list,
+ struct ocfs2_dx_root_block *dx_root,
+ struct ocfs2_dx_leaf *dx_leaf,
+ void *priv_data)
+{
+ FILE *out = priv_data;
+
+ if (dx_leaf) {
+ dump_dx_leaf(out, dx_leaf);
+ return 0;
+ }
+
+ /* Inline entries. Dump the list directly. */
+ dump_dx_entry_list(out, entry_list, 1);
+
+ return 0;
+}
+
+void dump_dx_entries(FILE *out, struct ocfs2_dinode *inode)
+{
+ struct ocfs2_dx_root_block *dx_root;
+ uint64_t dx_blkno;
+ char *buf = NULL;
+ errcode_t ret = 0;
+
+ if (ocfs2_malloc_block(gbls.fs->fs_io, &buf))
+ return;
+
+ if (!(ocfs2_dir_indexed(inode)))
+ return;
+
+ dx_blkno = (uint64_t) inode->i_dx_root;
+
+ ret = ocfs2_read_dx_root(gbls.fs, dx_blkno, buf);
+ if (ret)
+ return;
+
+ dx_root = (struct ocfs2_dx_root_block *)buf;
+ dump_dx_root(out, dx_root);
+
+ ocfs2_dx_entries_iterate(gbls.fs, inode, 0, entries_iter, out);
+ return;
+}
+
+static int dx_space_iter(ocfs2_filesys *fs,
+ uint64_t blkno,
+ struct ocfs2_dir_block_trailer *trailer,
+ char *dirblock,
+ void *priv_data)
+{
+ FILE *out = priv_data;
+
+ dump_dir_trailer(out, trailer);
+
+ return 0;
+}
+
+void dump_dx_space(FILE *out, struct ocfs2_dinode *inode,
+ struct ocfs2_dx_root_block *dx_root)
+{
+ ocfs2_dx_frees_iterate(gbls.fs, inode, dx_root, 0, dx_space_iter, out);
+}
+
/*
* dump_jbd_header()
*
diff --git a/debugfs.ocfs2/include/dump.h b/debugfs.ocfs2/include/dump.h
index cb677c9..79b10b3 100644
--- a/debugfs.ocfs2/include/dump.h
+++ b/debugfs.ocfs2/include/dump.h
@@ -52,7 +52,12 @@ void dump_extent_block (FILE *out, struct ocfs2_extent_block *blk);
void dump_group_descriptor (FILE *out, struct ocfs2_group_desc *grp, int index);
int dump_dir_entry (struct ocfs2_dir_entry *rec, int offset, int blocksize,
char *buf, void *priv_data);
+void dump_dx_root (FILE *out, struct ocfs2_dx_root_block *dx_root);
+void dump_dx_leaf (FILE *out, struct ocfs2_dx_leaf *dx_leaf);
void dump_dir_block(FILE *out, char *buf);
+void dump_dx_entries(FILE *out, struct ocfs2_dinode *inode);
+void dump_dx_space(FILE *out, struct ocfs2_dinode *inode,
+ struct ocfs2_dx_root_block *dx_root);
void dump_jbd_header (FILE *out, journal_header_t *header);
void dump_jbd_superblock (FILE *out, journal_superblock_t *jsb);
void dump_jbd_block (FILE *out, journal_superblock_t *jsb,
--
1.7.0.2

View File

@ -0,0 +1,73 @@
From 585f52a5dfd8cb4301d29804e7e05ddff1f3fca1 Mon Sep 17 00:00:00 2001
From: Mark Fasheh <mfasheh@suse.com>
Date: Sun, 11 Apr 2010 16:10:00 +0800
Subject: [PATCH 03/30] dx_dirs: mkfs.ocfs2 support
This adds only basic support to mkfs.ocfs2 to write the seed fields used
in directory indexing. The feature string
'indexed-dirs' is already there from a previous patch, so it is possible
to create a new file system with the directory
indexing feature turned on.
Future improvements that are needed:
- mkfs.ocfs2 should create the root directory and orphan dirs as
indexed.
- possibly also we want to do this for the system dir, but that might
require some discussion.
[modified the patch for code rebase and cleanup -- Coly Li]
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Signed-off-by: Coly Li <coly.li@suse.de>
---
mkfs.ocfs2/mkfs.c | 17 ++++++++++++++---
1 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/mkfs.ocfs2/mkfs.c b/mkfs.ocfs2/mkfs.c
index 5d01e3e..b43a9ba 100644
--- a/mkfs.ocfs2/mkfs.c
+++ b/mkfs.ocfs2/mkfs.c
@@ -1004,6 +1004,8 @@ get_state(int argc, char **argv)
if ((optind == argc) && !show_version)
usage(progname);
+ srand48(time(NULL));
+
device_name = argv[optind];
optind++;
@@ -2240,11 +2242,9 @@ format_superblock(State *s, SystemFileDiskRecord *rec,
*/
s->feature_flags.opt_compat &= ~OCFS2_FEATURE_COMPAT_BACKUP_SB;
- if (s->feature_flags.opt_incompat & OCFS2_FEATURE_INCOMPAT_XATTR) {
+ if (s->feature_flags.opt_incompat & OCFS2_FEATURE_INCOMPAT_XATTR)
di->id2.i_super.s_xattr_inline_size =
OCFS2_MIN_XATTR_INLINE_SIZE;
- di->id2.i_super.s_uuid_hash = ocfs2_xattr_uuid_hash(s->uuid);
- }
di->id2.i_super.s_feature_incompat = s->feature_flags.opt_incompat;
di->id2.i_super.s_feature_compat = s->feature_flags.opt_compat;
@@ -2253,6 +2253,17 @@ format_superblock(State *s, SystemFileDiskRecord *rec,
strcpy((char *)di->id2.i_super.s_label, s->vol_label);
memcpy(di->id2.i_super.s_uuid, s->uuid, 16);
+ /* s_uuid_hash is also used by Indexed Dirs */
+ if (s->feature_flags.opt_incompat & OCFS2_FEATURE_INCOMPAT_XATTR ||
+ s->feature_flags.opt_incompat & OCFS2_FEATURE_INCOMPAT_INDEXED_DIRS)
+ di->id2.i_super.s_uuid_hash = ocfs2_xattr_uuid_hash(s->uuid);
+
+ if (s->feature_flags.opt_incompat & OCFS2_FEATURE_INCOMPAT_INDEXED_DIRS) {
+ di->id2.i_super.s_dx_seed[0] = mrand48();
+ di->id2.i_super.s_dx_seed[1] = mrand48();
+ di->id2.i_super.s_dx_seed[2] = mrand48();
+ }
+
mkfs_swap_inode_from_cpu(s, di);
mkfs_compute_meta_ecc(s, di, &di->i_check);
do_pwrite(s, di, s->blocksize, super_off);
--
1.7.0.2

View File

@ -0,0 +1,149 @@
From 0afd7bae3557bd443eac4e388c0c3cbf47690e5d Mon Sep 17 00:00:00 2001
From: Mark Fasheh <mfasheh@suse.com>
Date: Sun, 11 Apr 2010 16:10:01 +0800
Subject: [PATCH 04/30] dx_dirs: Add tunefs.ocfs2 feature for indexed directories
This only enables them for now. Disabling is a bit more involved, and
will come later.
[modified the patch for code rebase and cleanup -- Coly Li]
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Signed-off-by: Coly Li <coly.li@suse.de>
---
tunefs.ocfs2/Makefile | 1 +
tunefs.ocfs2/feature_indexed_dirs.c | 89 +++++++++++++++++++++++++++++++++++
tunefs.ocfs2/op_features.c | 2 +
3 files changed, 92 insertions(+), 0 deletions(-)
create mode 100644 tunefs.ocfs2/feature_indexed_dirs.c
diff --git a/tunefs.ocfs2/Makefile b/tunefs.ocfs2/Makefile
index dad7034..6219af6 100644
--- a/tunefs.ocfs2/Makefile
+++ b/tunefs.ocfs2/Makefile
@@ -26,6 +26,7 @@ OCFS2NE_FEATURES = \
feature_sparse_files \
feature_unwritten_extents \
feature_xattr \
+ feature_indexed_dirs \
feature_quota
OCFS2NE_OPERATIONS = \
diff --git a/tunefs.ocfs2/feature_indexed_dirs.c b/tunefs.ocfs2/feature_indexed_dirs.c
new file mode 100644
index 0000000..368eb87
--- /dev/null
+++ b/tunefs.ocfs2/feature_indexed_dirs.c
@@ -0,0 +1,89 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * feature_indexed_dirs.c
+ *
+ * ocfs2 tune utility for enabling and disabling the directory indexing
+ * feature.
+ *
+ * Copyright (C) 2009 Novell. 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <inttypes.h>
+#include <assert.h>
+
+#include "ocfs2/ocfs2.h"
+
+#include "libocfs2ne.h"
+
+
+static int enable_indexed_dirs(ocfs2_filesys *fs, int flags)
+{
+ errcode_t ret = 0;
+ struct ocfs2_super_block *super = OCFS2_RAW_SB(fs->fs_super);
+ struct tools_progress *prog;
+
+ if (ocfs2_supports_indexed_dirs(super)) {
+ verbosef(VL_APP,
+ "Directory indexing feature is already enabled; "
+ "nothing to enable\n");
+ goto out;
+ }
+
+
+ if (!tools_interact("Enable the directory indexing feature on "
+ "device \"%s\"? ",
+ fs->fs_devname))
+ goto out;
+
+ prog = tools_progress_start("Enable directory indexing", "dir idx", 1);
+ if (!prog) {
+ ret = TUNEFS_ET_NO_MEMORY;
+ tcom_err(ret, "while initializing the progress display");
+ goto out;
+ }
+
+ OCFS2_SET_INCOMPAT_FEATURE(super,
+ OCFS2_FEATURE_INCOMPAT_INDEXED_DIRS);
+ tunefs_block_signals();
+ ret = ocfs2_write_super(fs);
+ tunefs_unblock_signals();
+ if (ret)
+ tcom_err(ret, "while writing out the superblock");
+
+ tools_progress_step(prog, 1);
+ tools_progress_stop(prog);
+out:
+ return ret;
+}
+
+/*
+ * TUNEFS_FLAG_ALLOCATION because disabling will want to dealloc
+ * blocks.
+ */
+DEFINE_TUNEFS_FEATURE_INCOMPAT(indexed_dirs,
+ OCFS2_FEATURE_INCOMPAT_INDEXED_DIRS,
+ TUNEFS_FLAG_RW | TUNEFS_FLAG_ALLOCATION,
+ enable_indexed_dirs,
+ NULL);
+
+#ifdef DEBUG_EXE
+int main(int argc, char *argv[])
+{
+ return tunefs_feature_main(argc, argv, &indexed_dirs_feature);
+}
+#endif
diff --git a/tunefs.ocfs2/op_features.c b/tunefs.ocfs2/op_features.c
index 91abca1..613ea7e 100644
--- a/tunefs.ocfs2/op_features.c
+++ b/tunefs.ocfs2/op_features.c
@@ -44,6 +44,7 @@ extern struct tunefs_feature xattr_feature;
extern struct tunefs_feature usrquota_feature;
extern struct tunefs_feature grpquota_feature;
extern struct tunefs_feature refcount_feature;
+extern struct tunefs_feature indexed_dirs_feature;
/* List of features supported by ocfs2ne */
static struct tunefs_feature *features[] = {
@@ -58,6 +59,7 @@ static struct tunefs_feature *features[] = {
&usrquota_feature,
&grpquota_feature,
&refcount_feature,
+ &indexed_dirs_feature,
NULL,
};
--
1.7.0.2

View File

@ -0,0 +1,62 @@
From 56f5ac553c2686271b657ed8be4f8ca001aa7ed6 Mon Sep 17 00:00:00 2001
From: Mark Fasheh <mfasheh@suse.com>
Date: Sun, 11 Apr 2010 16:10:02 +0800
Subject: [PATCH 05/30] dx_dirs: Update for dr_num_entries
This just adds the new field, swaps it appropriately, and prints it in
debuggs.
[Modified the patch for code rebase and cleanup -- Coly Li]
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Signed-off-by: Coly Li <coly.li@suse.de>
---
debugfs.ocfs2/dump.c | 2 ++
include/ocfs2-kernel/ocfs2_fs.h | 5 ++++-
libocfs2/dirblock.c | 1 +
3 files changed, 7 insertions(+), 1 deletions(-)
diff --git a/debugfs.ocfs2/dump.c b/debugfs.ocfs2/dump.c
index 2e887ce..88ec430 100644
--- a/debugfs.ocfs2/dump.c
+++ b/debugfs.ocfs2/dump.c
@@ -600,6 +600,8 @@ void dump_dx_root(FILE *out, struct ocfs2_dx_root_block *dr)
"Flags: (0x%x) %s\n",
tmp_str, dr->dr_suballoc_bit, dr->dr_flags, flags->str);
+ fprintf(out, "\tTotal Entry Count: %d\n", dr->dr_num_entries);
+
dump_block_check(out, &dr->dr_check);
if (dr->dr_flags & OCFS2_DX_FLAG_INLINE)
diff --git a/include/ocfs2-kernel/ocfs2_fs.h b/include/ocfs2-kernel/ocfs2_fs.h
index d4de181..f3c2450 100644
--- a/include/ocfs2-kernel/ocfs2_fs.h
+++ b/include/ocfs2-kernel/ocfs2_fs.h
@@ -810,7 +810,10 @@ struct ocfs2_dx_root_block {
__u8 dr_reserved0;
__le16 dr_reserved1;
__le64 dr_dir_blkno; /* Pointer to parent inode */
- __le64 dr_reserved2;
+ __le32 dr_num_entries; /* Total number of
+ * names stored in
+ * this directory.*/
+ __le32 dr_reserved2;
__le64 dr_free_blk; /* Pointer to head of free
* unindexed block list. */
__le64 dr_reserved3[15];
diff --git a/libocfs2/dirblock.c b/libocfs2/dirblock.c
index d68e5c0..4bf48f3 100644
--- a/libocfs2/dirblock.c
+++ b/libocfs2/dirblock.c
@@ -266,6 +266,7 @@ static void ocfs2_swap_dx_root_to_cpu(struct ocfs2_dx_root_block *dx_root)
dx_root->dr_last_eb_blk = bswap_64(dx_root->dr_last_eb_blk);
dx_root->dr_clusters = bswap_32(dx_root->dr_clusters);
dx_root->dr_dir_blkno = bswap_64(dx_root->dr_dir_blkno);
+ dx_root->dr_num_entries = bswap_32(dx_root->dr_num_entries);
dx_root->dr_free_blk = bswap_64(dx_root->dr_free_blk);
if (dx_root->dr_flags & OCFS2_DX_FLAG_INLINE)
--
1.7.0.2

View File

@ -0,0 +1,50 @@
From 5110de09d64c84037e7e2ecdf76ab2d0d0f77ff4 Mon Sep 17 00:00:00 2001
From: Coly Li <coly.li@suse.de>
Date: Sun, 11 Apr 2010 16:10:03 +0800
Subject: [PATCH 06/30] dx_dirs: add missing 'ocfs2_filesys *fs' parameter
This patch add 'ocfs2_filesys *fs' parameter to
ocfs2_swap_dx_root_to_cpu(), and fix the mismatched arguments when
alling ocfs2_swap_extent_list_to_cpu().
Signed-off-by: Coly Li <coly.li@suse.de>
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
---
libocfs2/dirblock.c | 7 ++++---
1 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/libocfs2/dirblock.c b/libocfs2/dirblock.c
index 4bf48f3..06a1b64 100644
--- a/libocfs2/dirblock.c
+++ b/libocfs2/dirblock.c
@@ -254,7 +254,8 @@ static void ocfs2_swap_dx_entry_list_to_cpu(struct ocfs2_dx_entry_list *dl_list)
ocfs2_swap_dx_entry_to_cpu(&dl_list->de_entries[i]);
}
-static void ocfs2_swap_dx_root_to_cpu(struct ocfs2_dx_root_block *dx_root)
+static void ocfs2_swap_dx_root_to_cpu(ocfs2_filesys *fs,
+ struct ocfs2_dx_root_block *dx_root)
{
if (cpu_is_little_endian)
return;
@@ -272,7 +273,7 @@ static void ocfs2_swap_dx_root_to_cpu(struct ocfs2_dx_root_block *dx_root)
if (dx_root->dr_flags & OCFS2_DX_FLAG_INLINE)
ocfs2_swap_dx_entry_list_to_cpu(&dx_root->dr_entries);
else
- ocfs2_swap_extent_list_to_cpu(&dx_root->dr_list);
+ ocfs2_swap_extent_list_to_cpu(fs, dx_root, &dx_root->dr_list);
}
errcode_t ocfs2_read_dx_root(ocfs2_filesys *fs, uint64_t block,
@@ -294,7 +295,7 @@ errcode_t ocfs2_read_dx_root(ocfs2_filesys *fs, uint64_t block,
strlen(OCFS2_DX_ROOT_SIGNATURE)))
return OCFS2_ET_DIR_CORRUPTED;
- ocfs2_swap_dx_root_to_cpu(dx_root);
+ ocfs2_swap_dx_root_to_cpu(fs, dx_root);
return 0;
}
--
1.7.0.2

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,415 @@
From 2bbbdef8534534b12cf3dd3ad9db6a1ebd74d0a3 Mon Sep 17 00:00:00 2001
From: Coly Li <coly.li@suse.de>
Date: Sun, 11 Apr 2010 16:10:05 +0800
Subject: [PATCH 08/30] dx_dirs: fsck.ocfs2 support
This patch does a basic indexed dirs support in fsck.ocfs2.
During pass2, if a directory block is changed, and indexed dirs in
enabled, the indexed tree of this directory will be
truncate, then rebuild with the modified directory data. All the
modified directories' inode numbers are recored in a
rb-tree, when all directories get scanned, truncate and rebuild the
directories whose inode recorded in the rb-tree.
Signed-off-by: Coly Li <coly.li@suse.de>
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
---
fsck.ocfs2/dirblocks.c | 125 ++++++++++++++++++++++++++++++++++++++-
fsck.ocfs2/include/dirblocks.h | 4 +
fsck.ocfs2/pass1.c | 54 +++++++++++++++++
fsck.ocfs2/pass1b.c | 4 +-
fsck.ocfs2/pass2.c | 48 +++++++++++++++-
fsck.ocfs2/pass3.c | 1 +
fsck.ocfs2/pass4.c | 1 +
7 files changed, 229 insertions(+), 8 deletions(-)
diff --git a/fsck.ocfs2/dirblocks.c b/fsck.ocfs2/dirblocks.c
index 1fd5560..085dd1f 100644
--- a/fsck.ocfs2/dirblocks.c
+++ b/fsck.ocfs2/dirblocks.c
@@ -34,6 +34,7 @@
#include "fsck.h"
#include "dirblocks.h"
#include "util.h"
+#include "extent.h"
errcode_t o2fsck_add_dir_block(o2fsck_dirblocks *db, uint64_t ino,
uint64_t blkno, uint64_t blkcount)
@@ -43,11 +44,9 @@ errcode_t o2fsck_add_dir_block(o2fsck_dirblocks *db, uint64_t ino,
o2fsck_dirblock_entry *dbe, *tmp_dbe;
errcode_t ret = 0;
- dbe = calloc(1, sizeof(*dbe));
- if (dbe == NULL) {
- ret = OCFS2_ET_NO_MEMORY;
+ ret = ocfs2_malloc0(sizeof(o2fsck_dirblock_entry), &dbe);
+ if (ret)
goto out;
- }
dbe->e_ino = ino;
dbe->e_blkno = blkno;
@@ -134,6 +133,73 @@ static int try_to_cache(ocfs2_filesys *fs, struct rb_node *node,
return cached_blocks;
}
+uint64_t o2fsck_search_reidx_dir(struct rb_root *root, uint64_t dino)
+{
+ struct rb_node *node = root->rb_node;
+ o2fsck_dirblock_entry *dbe;
+
+ while (node) {
+ dbe = rb_entry(node, o2fsck_dirblock_entry, e_node);
+
+ if (dino < dbe->e_ino)
+ node = node->rb_left;
+ else if (dino > dbe->e_ino)
+ node = node->rb_right;
+ else
+ return dbe->e_ino;
+ }
+ return 0;
+}
+
+static errcode_t o2fsck_add_reidx_dir_ino(struct rb_root *root, uint64_t dino)
+{
+ struct rb_node **p = &root->rb_node;
+ struct rb_node *parent = NULL;
+ o2fsck_dirblock_entry *dp, *tmp_dp;
+ errcode_t ret = 0;
+
+ ret = ocfs2_malloc0(sizeof (o2fsck_dirblock_entry), &dp);
+ if (ret)
+ goto out;
+
+ dp->e_ino = dino;
+
+ while(*p)
+ {
+ parent = *p;
+ tmp_dp = rb_entry(parent, o2fsck_dirblock_entry, e_node);
+
+ if (dp->e_ino < tmp_dp->e_ino)
+ p = &(*p)->rb_left;
+ else if (dp->e_ino > tmp_dp->e_ino)
+ p = &(*p)->rb_right;
+ else {
+ ret = OCFS2_ET_INTERNAL_FAILURE;
+ ocfs2_free(&dp);
+ goto out;
+ }
+ }
+
+ rb_link_node(&dp->e_node, parent, p);
+ rb_insert_color(&dp->e_node, root);
+
+out:
+ return ret;
+}
+
+errcode_t o2fsck_try_add_reidx_dir(struct rb_root *root, uint64_t dino)
+{
+ errcode_t ret = 0;
+ uint64_t ino;
+ ino = o2fsck_search_reidx_dir(root, dino);
+ if (ino)
+ goto out;
+ ret = o2fsck_add_reidx_dir_ino(root, dino);
+
+out:
+ return ret;
+}
+
void o2fsck_dir_block_iterate(o2fsck_state *ost, dirblock_iterator func,
void *priv_data)
{
@@ -174,3 +240,54 @@ void o2fsck_dir_block_iterate(o2fsck_state *ost, dirblock_iterator func,
if (pre_cache_buf)
ocfs2_free(&pre_cache_buf);
}
+
+static errcode_t ocfs2_rebuild_indexed_dir(ocfs2_filesys *fs, uint64_t ino)
+{
+ errcode_t ret = 0;
+ char *di_buf = NULL;
+ struct ocfs2_dinode *di;
+
+
+ ret = ocfs2_malloc_block(fs->fs_io, &di_buf);
+ if (ret)
+ goto out;
+
+ ret = ocfs2_read_inode(fs, ino, di_buf);
+ if (ret)
+ goto out;
+ di = (struct ocfs2_dinode *)di_buf;
+
+ /* do not rebuild indexed tree for inline directory */
+ if (di->i_dyn_features & OCFS2_INLINE_DATA_FL)
+ goto out;
+
+ ret = ocfs2_dx_dir_truncate(fs, ino);
+ if (ret)
+ goto out;
+
+ ret = ocfs2_dx_dir_build(fs, ino);
+out:
+ if (di_buf)
+ ocfs2_free(&di_buf);
+ return ret;
+}
+
+
+errcode_t o2fsck_rebuild_indexed_dirs(ocfs2_filesys *fs, struct rb_root *root)
+{
+ struct rb_node *node;
+ o2fsck_dirblock_entry *dbe;
+ uint64_t ino;
+ errcode_t ret = 0;
+
+ for (node = rb_first(root); node; node = rb_next(node)) {
+ dbe = rb_entry(node, o2fsck_dirblock_entry, e_node);
+ ino = dbe->e_ino;
+ ret = ocfs2_rebuild_indexed_dir(fs, ino);
+ if (ret)
+ goto out;
+ }
+out:
+ return ret;
+}
+
diff --git a/fsck.ocfs2/include/dirblocks.h b/fsck.ocfs2/include/dirblocks.h
index 7b3a2e9..f85974f 100644
--- a/fsck.ocfs2/include/dirblocks.h
+++ b/fsck.ocfs2/include/dirblocks.h
@@ -48,6 +48,10 @@ struct _o2fsck_state;
void o2fsck_dir_block_iterate(struct _o2fsck_state *ost, dirblock_iterator func,
void *priv_data);
+uint64_t o2fsck_search_reidx_dir(struct rb_root *root, uint64_t dino);
+errcode_t o2fsck_try_add_reidx_dir(struct rb_root *root, uint64_t dino);
+errcode_t o2fsck_rebuild_indexed_dirs(ocfs2_filesys *fs, struct rb_root *root);
+errcode_t o2fsck_check_dir_index(struct _o2fsck_state *ost, struct ocfs2_dinode *di);
#endif /* __O2FSCK_DIRBLOCKS_H__ */
diff --git a/fsck.ocfs2/pass1.c b/fsck.ocfs2/pass1.c
index 00f3d54..b53b908 100644
--- a/fsck.ocfs2/pass1.c
+++ b/fsck.ocfs2/pass1.c
@@ -781,6 +781,53 @@ static int clear_block(ocfs2_filesys *fs,
return 0;
}
+
+static errcode_t o2fsck_check_dx_dir(o2fsck_state *ost, struct ocfs2_dinode *di)
+{
+ errcode_t ret = 0;
+ char *buf = NULL;
+ struct ocfs2_dx_root_block *dx_root;
+ ocfs2_filesys *fs = ost->ost_fs;
+ struct extent_info ei = {0,};
+ int changed = 0;
+
+ if (!ocfs2_supports_indexed_dirs(OCFS2_RAW_SB(fs->fs_super)))
+ goto out;
+
+ if (!ocfs2_dir_indexed(di))
+ goto out;
+
+ ret = ocfs2_malloc_block(fs->fs_io, &buf);
+ if (ret)
+ goto out;
+
+ ret = ocfs2_read_dx_root(fs, (uint64_t)di->i_dx_root, buf);
+ if (ret)
+ goto out;
+
+ dx_root = (struct ocfs2_dx_root_block *)buf;
+ if (dx_root->dr_flags & OCFS2_DX_FLAG_INLINE)
+ goto out;
+
+ ret = check_el(ost, &ei, di->i_blkno, &dx_root->dr_list,
+ ocfs2_extent_recs_per_dx_root(fs->fs_blocksize),
+ &changed);
+ if (ret)
+ goto out;
+
+ if (changed) {
+ ret = ocfs2_write_dx_root(fs, (uint64_t)di->i_dx_root, (char *)dx_root);
+ if (ret)
+ com_err(whoami, ret, "while writing an updated "
+ "dx_root block at %"PRIu64" for inode %"PRIu64,
+ (uint64_t)di->i_dx_root, (uint64_t)di->i_blkno);
+ }
+out:
+ if (buf)
+ ocfs2_free(&buf);
+ return ret;
+}
+
/*
* this verifies i_size and i_clusters for inodes that use i_list to
* reference extents of data.
@@ -836,6 +883,13 @@ static errcode_t o2fsck_check_blocks(ocfs2_filesys *fs, o2fsck_state *ost,
goto out;
}
+ ret = o2fsck_check_dx_dir(ost, di);
+ if (ret) {
+ com_err(whoami, ret, "while iterating over the dir indexed "
+ "tree for directory inode %"PRIu64, (uint64_t)di->i_blkno);
+ goto out;
+ }
+
if (S_ISLNK(di->i_mode))
check_link_data(&vb);
diff --git a/fsck.ocfs2/pass1b.c b/fsck.ocfs2/pass1b.c
index 0ea87b4..3ca1d7d 100644
--- a/fsck.ocfs2/pass1b.c
+++ b/fsck.ocfs2/pass1b.c
@@ -902,8 +902,8 @@ static void name_inode(struct dir_scan_context *scan,
pass1c_warn(OCFS2_ET_NO_MEMORY);
}
-static int walk_iterate(struct ocfs2_dir_entry *de, int offset,
- int blocksize, char *buf, void *priv_data)
+static int walk_iterate(struct ocfs2_dir_entry *de, uint64_t blocknr,
+ int offset, int blocksize, char *buf, void *priv_data)
{
struct dir_scan_context *scan = priv_data;
diff --git a/fsck.ocfs2/pass2.c b/fsck.ocfs2/pass2.c
index d61c501..58efcd4 100644
--- a/fsck.ocfs2/pass2.c
+++ b/fsck.ocfs2/pass2.c
@@ -36,6 +36,7 @@
#include <time.h>
#include "ocfs2/ocfs2.h"
+#include "ocfs2/kernel-rbtree.h"
#include "dirparents.h"
#include "icount.h"
@@ -70,6 +71,7 @@ struct dirblock_data {
errcode_t ret;
o2fsck_strings strings;
uint64_t last_ino;
+ struct rb_root re_idx_dirs;
};
static int dirent_has_dots(struct ocfs2_dir_entry *dirent, int num_dots)
@@ -833,10 +835,11 @@ next:
}
if (ocfs2_dir_has_trailer(dd->fs, di))
- fix_dir_trailer(dd->ost, dbe,
+ fix_dir_trailer(dd->ost,
+ dbe,
ocfs2_dir_trailer_from_block(dd->fs,
dd->dirblock_buf),
- &ret_flags);
+ &ret_flags);
if (ret_flags & OCFS2_DIRENT_CHANGED) {
if (di->i_dyn_features & OCFS2_INLINE_DATA_FL) {
@@ -851,15 +854,47 @@ next:
com_err(whoami, ret, "while writing dir block %"PRIu64,
dbe->e_blkno);
dd->ost->ost_write_error = 1;
+ goto out;
+ }
+
+ if (ocfs2_supports_indexed_dirs(OCFS2_RAW_SB(dd->fs->fs_super)) &&
+ !(di->i_dyn_features & OCFS2_INLINE_DATA_FL) &&
+ (di->i_dyn_features & OCFS2_INDEXED_DIR_FL)) {
+ ret = o2fsck_try_add_reidx_dir(&dd->re_idx_dirs, dbe->e_ino);
+ if (ret) {
+ com_err(whoami, ret, "while adding block for "
+ "directory inode %"PRIu64" to rebuild "
+ "dir index", dbe->e_ino);
+ goto out;
+ }
}
}
+ /* truncate invalid indexed tree */
+ if ((!ocfs2_supports_indexed_dirs(OCFS2_RAW_SB(dd->fs->fs_super)))&&
+ di->i_dyn_features & OCFS2_INDEXED_DIR_FL ) {
+ /* ignore the return value */
+ ocfs2_dx_dir_truncate(dd->fs, dbe->e_ino);
+ }
+
out:
if (ret)
dd->ret = ret;
return ret_flags;
}
+static void release_re_idx_dirs_rbtree(struct rb_root * root)
+{
+ struct rb_node *node;
+ o2fsck_dirblock_entry *dp;
+
+ while ((node = rb_first(root)) != NULL) {
+ dp = rb_entry(node, o2fsck_dirblock_entry, e_node);
+ rb_erase(&dp->e_node, root);
+ ocfs2_free(&dp);
+ }
+}
+
errcode_t o2fsck_pass2(o2fsck_state *ost)
{
o2fsck_dir_parent *dp;
@@ -868,6 +903,7 @@ errcode_t o2fsck_pass2(o2fsck_state *ost)
.ost = ost,
.fs = ost->ost_fs,
.last_ino = 0,
+ .re_idx_dirs = RB_ROOT,
};
printf("Pass 2: Checking directory entries.\n");
@@ -905,6 +941,14 @@ errcode_t o2fsck_pass2(o2fsck_state *ost)
dp->dp_dirent = ost->ost_fs->fs_sysdir_blkno;
o2fsck_dir_block_iterate(ost, pass2_dir_block_iterate, &dd);
+
+ if (dd.re_idx_dirs.rb_node) {
+ ret = o2fsck_rebuild_indexed_dirs(ost->ost_fs, &dd.re_idx_dirs);
+ if (ret)
+ com_err(whoami, ret, "while rebuild indexed dirs.");
+ }
+ release_re_idx_dirs_rbtree(&dd.re_idx_dirs);
+
o2fsck_strings_free(&dd.strings);
out:
if (dd.dirblock_buf)
diff --git a/fsck.ocfs2/pass3.c b/fsck.ocfs2/pass3.c
index 457f312..94d9fbd 100644
--- a/fsck.ocfs2/pass3.c
+++ b/fsck.ocfs2/pass3.c
@@ -193,6 +193,7 @@ struct fix_dot_dot_args {
};
static int fix_dot_dot_dirent(struct ocfs2_dir_entry *dirent,
+ uint64_t blocknr,
int offset,
int blocksize,
char *buf,
diff --git a/fsck.ocfs2/pass4.c b/fsck.ocfs2/pass4.c
index d713d13..5ca4f17 100644
--- a/fsck.ocfs2/pass4.c
+++ b/fsck.ocfs2/pass4.c
@@ -101,6 +101,7 @@ out:
}
static int replay_orphan_iterate(struct ocfs2_dir_entry *dirent,
+ uint64_t blocknr,
int offset,
int blocksize,
char *buf,
--
1.7.0.2

View File

@ -0,0 +1,217 @@
From c797d07a1021d5c3a5541236739dabb5dfd4c620 Mon Sep 17 00:00:00 2001
From: Coly Li <coly.li@suse.de>
Date: Sun, 11 Apr 2010 16:10:06 +0800
Subject: [PATCH 09/30] dx_dirs: add 'blocknr' in callback of ocfs2_dir_iterate()
In order to make ocfs2_dx_dir_insert() easier to set the dir block
number to a dx record, a new parameter 'uint64_t
blocknr' is added into the call back function parameter of
ocfs2_dir_iterate(). This patch includes (part of) the
related changes which are not mentioned in previous patches.
Signed-off-by: Coly Li <coly.li@suse.de>
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
---
debugfs.ocfs2/dump.c | 6 +++---
debugfs.ocfs2/find_inode_paths.c | 3 ++-
debugfs.ocfs2/include/dump.h | 2 +-
debugfs.ocfs2/utils.c | 4 ++--
extras/find_hardlinks.c | 1 +
extras/find_inode_paths.c | 1 +
fswreck/dir.c | 3 +++
ocfs2console/ocfs2interface/ocfs2module.c | 1 +
tunefs.ocfs2/feature_quota.c | 3 ++-
tunefs.ocfs2/op_list_sparse_files.c | 4 ++--
tunefs.ocfs2/op_set_slot_count.c | 10 ++++++----
11 files changed, 24 insertions(+), 14 deletions(-)
diff --git a/debugfs.ocfs2/dump.c b/debugfs.ocfs2/dump.c
index 88ec430..d55fc0e 100644
--- a/debugfs.ocfs2/dump.c
+++ b/debugfs.ocfs2/dump.c
@@ -461,8 +461,8 @@ void dump_group_descriptor (FILE *out, struct ocfs2_group_desc *grp,
* dump_dir_entry()
*
*/
-int dump_dir_entry (struct ocfs2_dir_entry *rec, int offset, int blocksize,
- char *buf, void *priv_data)
+int dump_dir_entry (struct ocfs2_dir_entry *rec, uint64_t blocknr, int offset,
+ int blocksize, char *buf, void *priv_data)
{
list_dir_opts *ls = (list_dir_opts *)priv_data;
char tmp = rec->name[rec->name_len];
@@ -544,7 +544,7 @@ void dump_dir_block(FILE *out, char *buf)
return;
}
- dump_dir_entry(dirent, offset, gbls.fs->fs_blocksize, NULL,
+ dump_dir_entry(dirent, 0, offset, gbls.fs->fs_blocksize, NULL,
&ls_opts);
offset += dirent->rec_len;
}
diff --git a/debugfs.ocfs2/find_inode_paths.c b/debugfs.ocfs2/find_inode_paths.c
index e2d0e7d..cf9e88a 100644
--- a/debugfs.ocfs2/find_inode_paths.c
+++ b/debugfs.ocfs2/find_inode_paths.c
@@ -38,7 +38,8 @@ struct walk_path {
uint64_t *inode;
};
-static int walk_tree_func(struct ocfs2_dir_entry *dentry, int offset,
+static int walk_tree_func(struct ocfs2_dir_entry *dentry,
+ uint64_t blocknr, int offset,
int blocksize, char *buf, void *priv_data)
{
errcode_t ret;
diff --git a/debugfs.ocfs2/include/dump.h b/debugfs.ocfs2/include/dump.h
index 79b10b3..ae7b34a 100644
--- a/debugfs.ocfs2/include/dump.h
+++ b/debugfs.ocfs2/include/dump.h
@@ -50,7 +50,7 @@ void dump_extent_list (FILE *out, struct ocfs2_extent_list *ext);
void dump_chain_list (FILE *out, struct ocfs2_chain_list *cl);
void dump_extent_block (FILE *out, struct ocfs2_extent_block *blk);
void dump_group_descriptor (FILE *out, struct ocfs2_group_desc *grp, int index);
-int dump_dir_entry (struct ocfs2_dir_entry *rec, int offset, int blocksize,
+int dump_dir_entry (struct ocfs2_dir_entry *rec, uint64_t blocknr, int offset, int blocksize,
char *buf, void *priv_data);
void dump_dx_root (FILE *out, struct ocfs2_dx_root_block *dx_root);
void dump_dx_leaf (FILE *out, struct ocfs2_dx_leaf *dx_leaf);
diff --git a/debugfs.ocfs2/utils.c b/debugfs.ocfs2/utils.c
index 6107d9e..2c5b588 100644
--- a/debugfs.ocfs2/utils.c
+++ b/debugfs.ocfs2/utils.c
@@ -674,8 +674,8 @@ bail:
* Copyright (C) 1994 Theodore Ts'o. This file may be redistributed
* under the terms of the GNU Public License.
*/
-static int rdump_dirent(struct ocfs2_dir_entry *rec, int offset, int blocksize,
- char *buf, void *priv_data)
+static int rdump_dirent(struct ocfs2_dir_entry *rec, uint64_t blocknr,
+ int offset, int blocksize, char *buf, void *priv_data)
{
rdump_opts *rd = (rdump_opts *)priv_data;
char tmp = rec->name[rec->name_len];
diff --git a/extras/find_hardlinks.c b/extras/find_hardlinks.c
index b70f58b..2e1f697 100644
--- a/extras/find_hardlinks.c
+++ b/extras/find_hardlinks.c
@@ -55,6 +55,7 @@ struct walk_path {
};
static int walk_tree_func(struct ocfs2_dir_entry *dentry,
+ uint64_t blocknr,
int offset,
int blocksize,
char *buf,
diff --git a/extras/find_inode_paths.c b/extras/find_inode_paths.c
index 1725b40..b9ad920 100644
--- a/extras/find_inode_paths.c
+++ b/extras/find_inode_paths.c
@@ -53,6 +53,7 @@ struct walk_path {
};
static int walk_tree_func(struct ocfs2_dir_entry *dentry,
+ uint64_t blocknr,
int offset,
int blocksize,
char *buf,
diff --git a/fswreck/dir.c b/fswreck/dir.c
index 66309fd..eb8d0f2 100644
--- a/fswreck/dir.c
+++ b/fswreck/dir.c
@@ -112,6 +112,7 @@ static int corrupt_match_dirent(struct dirent_corrupt_struct *dcs,
}
static int rename_dirent_proc(struct ocfs2_dir_entry *dirent,
+ uint64_t blocknr,
int offset,
int blocksize,
char *buf,
@@ -157,6 +158,7 @@ static int rename_dirent(ocfs2_filesys *fs, uint64_t dir,
}
static int corrupt_dirent_ino_proc(struct ocfs2_dir_entry *dirent,
+ uint64_t blocknr,
int offset,
int blocksize,
char *buf,
@@ -200,6 +202,7 @@ static int corrupt_dirent_ino(ocfs2_filesys *fs, uint64_t dir,
}
static int corrupt_dirent_reclen_proc(struct ocfs2_dir_entry *dirent,
+ uint64_t blocknr,
int offset,
int blocksize,
char *buf,
diff --git a/ocfs2console/ocfs2interface/ocfs2module.c b/ocfs2console/ocfs2interface/ocfs2module.c
index bd3139d..18ad04c 100644
--- a/ocfs2console/ocfs2interface/ocfs2module.c
+++ b/ocfs2console/ocfs2interface/ocfs2module.c
@@ -735,6 +735,7 @@ typedef struct
static int
walk_dirs (struct ocfs2_dir_entry *dirent,
+ uint64_t blocknr,
int offset,
int blocksize,
char *buf,
diff --git a/tunefs.ocfs2/feature_quota.c b/tunefs.ocfs2/feature_quota.c
index 2da3cbe..08d7770 100644
--- a/tunefs.ocfs2/feature_quota.c
+++ b/tunefs.ocfs2/feature_quota.c
@@ -165,7 +165,8 @@ struct remove_quota_files_ctxt {
};
static int remove_quota_files_iterate(struct ocfs2_dir_entry *dirent,
- int offset, int blocksize, char *buf,
+ uint64_t blocknr, int offset,
+ int blocksize, char *buf,
void *priv_data)
{
struct remove_quota_files_ctxt *ctxt = priv_data;
diff --git a/tunefs.ocfs2/op_list_sparse_files.c b/tunefs.ocfs2/op_list_sparse_files.c
index 2f81d36..3127876 100644
--- a/tunefs.ocfs2/op_list_sparse_files.c
+++ b/tunefs.ocfs2/op_list_sparse_files.c
@@ -290,8 +290,8 @@ bail:
}
static int list_sparse_func(struct ocfs2_dir_entry *dirent,
- int offset, int blocksize,
- char *buf, void *priv_data)
+ uint64_t blocknr, int offset,
+ int blocksize, char *buf, void *priv_data)
{
errcode_t ret;
char *di_buf = NULL;
diff --git a/tunefs.ocfs2/op_set_slot_count.c b/tunefs.ocfs2/op_set_slot_count.c
index 46ce2de..cdd4f1a 100644
--- a/tunefs.ocfs2/op_set_slot_count.c
+++ b/tunefs.ocfs2/op_set_slot_count.c
@@ -699,8 +699,9 @@ static errcode_t truncate_orphan_dir(ocfs2_filesys *fs,
return ret;
}
-static int remove_slot_iterate(struct ocfs2_dir_entry *dirent, int offset,
- int blocksize, char *buf, void *priv_data)
+static int remove_slot_iterate(struct ocfs2_dir_entry *dirent,
+ uint64_t blocknr, int offset, int blocksize,
+ char *buf, void *priv_data)
{
struct remove_slot_ctxt *ctxt =
(struct remove_slot_ctxt *)priv_data;
@@ -783,8 +784,9 @@ bail:
return ret;
}
-static int orphan_iterate(struct ocfs2_dir_entry *dirent, int offset,
- int blocksize, char *buf, void *priv_data)
+static int orphan_iterate(struct ocfs2_dir_entry *dirent,
+ uint64_t blocknr, int offset, int blocksize,
+ char *buf, void *priv_data)
{
int *has_orphan = (int *)priv_data;
--
1.7.0.2

View File

@ -0,0 +1,261 @@
From 88ed9a6f3d2bb06220c9188ad333b668b3936268 Mon Sep 17 00:00:00 2001
From: Coly Li <coly.li@suse.de>
Date: Sun, 11 Apr 2010 16:10:07 +0800
Subject: [PATCH 10/30] dx_dirs: add disable indexed-dirs support in tunefs.ocfs2
This patch truncates all directories' indexed tree if '--fs-features
noindexed-tree' option is given. The indexed dirs
related flags on directory inodes and superblock are cleared too.
Signed-off-by: Coly Li <coly.li@suse.de>
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
---
tunefs.ocfs2/feature_indexed_dirs.c | 192 ++++++++++++++++++++++++++++++++++-
tunefs.ocfs2/o2ne_err.et | 9 ++
2 files changed, 199 insertions(+), 2 deletions(-)
diff --git a/tunefs.ocfs2/feature_indexed_dirs.c b/tunefs.ocfs2/feature_indexed_dirs.c
index 368eb87..e9f87fb 100644
--- a/tunefs.ocfs2/feature_indexed_dirs.c
+++ b/tunefs.ocfs2/feature_indexed_dirs.c
@@ -6,7 +6,7 @@
* ocfs2 tune utility for enabling and disabling the directory indexing
* feature.
*
- * Copyright (C) 2009 Novell. All rights reserved.
+ * Copyright (C) 2009, 2010 Novell. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
@@ -30,6 +30,17 @@
#include "libocfs2ne.h"
+struct dx_dirs_inode {
+ struct list_head list;
+ uint64_t ino;
+};
+
+struct dx_dirs_context {
+ errcode_t ret;
+ uint64_t dx_dirs_nr;
+ struct list_head inodes;
+ struct tools_progress *prog;
+};
static int enable_indexed_dirs(ocfs2_filesys *fs, int flags)
{
@@ -71,6 +82,183 @@ out:
return ret;
}
+static errcode_t dx_dir_iterate(ocfs2_filesys *fs, struct ocfs2_dinode *di,
+ void *user_data)
+{
+ errcode_t ret = 0;
+ struct dx_dirs_inode *dx_di = NULL;
+ struct dx_dirs_context *ctxt= (struct dx_dirs_context *)user_data;
+
+ if (!S_ISDIR(di->i_mode))
+ goto bail;
+
+ if (!(di->i_dyn_features & OCFS2_INDEXED_DIR_FL))
+ goto bail;
+
+ ret = ocfs2_malloc0(sizeof(struct dx_dirs_inode), &dx_di);
+ if (ret) {
+ ret = TUNEFS_ET_NO_MEMORY;
+ goto bail;
+ }
+
+ dx_di->ino = di->i_blkno;
+ ctxt->dx_dirs_nr ++;
+ list_add_tail(&dx_di->list, &ctxt->inodes);
+
+ tools_progress_step(ctxt->prog, 1);
+
+bail:
+ return ret;
+}
+
+
+static errcode_t find_indexed_dirs(ocfs2_filesys *fs,
+ struct dx_dirs_context *ctxt)
+{
+ errcode_t ret;
+
+ ctxt->prog = tools_progress_start("Scanning filesystem", "scanning", 0);
+ if (!ctxt->prog) {
+ ret = TUNEFS_ET_NO_MEMORY;
+ goto bail;
+ }
+
+ ret = tunefs_foreach_inode(fs, dx_dir_iterate, ctxt);
+ if (ret) {
+ if (ret != TUNEFS_ET_NO_MEMORY)
+ ret = TUNEFS_ET_DX_DIRS_SCAN_FAILED;
+ goto bail;
+ }
+
+ verbosef(VL_APP,
+ "We have %lu indexed %s to truncate.\n",
+ ctxt->dx_dirs_nr,
+ (ctxt->dx_dirs_nr > 1)?"directories":"directory");
+
+bail:
+ if (ctxt->prog)
+ tools_progress_stop(ctxt->prog);
+
+ return ret;
+}
+
+static errcode_t clean_indexed_dirs(ocfs2_filesys *fs,
+ struct dx_dirs_context *ctxt)
+{
+ errcode_t ret = 0;
+ struct list_head *pos;
+ struct dx_dirs_inode *dx_di;
+ struct tools_progress *prog;
+ uint64_t dirs_truncated = 0;
+
+ prog = tools_progress_start("Truncating indexed dirs", "truncating",
+ ctxt->dx_dirs_nr);
+ if (!prog) {
+ ret = TUNEFS_ET_NO_MEMORY;
+ goto bail;
+ }
+
+ list_for_each(pos, &ctxt->inodes) {
+ dx_di = list_entry(pos, struct dx_dirs_inode, list);
+
+ ret = ocfs2_dx_dir_truncate(fs, dx_di->ino);
+ if (ret) {
+ verbosef(VL_APP,
+ "Truncate directory (ino \"%lu\") failed.",
+ dx_di->ino);
+ ret = TUNEFS_ET_DX_DIRS_TRUNCATE_FAILED;
+ goto bail;
+ }
+ dirs_truncated ++;
+ tools_progress_step(prog, 1);
+ }
+
+bail:
+ tools_progress_stop(prog);
+ verbosef(VL_APP,
+ "\"%lu\" from \"%lu\" indexed %s truncated.",
+ dirs_truncated, ctxt->dx_dirs_nr,
+ (dirs_truncated <= 1) ? "directory is" : "directories are");
+
+ return ret;
+}
+
+static void release_dx_dirs_context(struct dx_dirs_context *ctxt)
+{
+ struct list_head *pos, *n;
+ struct dx_dirs_inode *dx_di;
+
+ list_for_each_safe(pos, n, &ctxt->inodes) {
+ dx_di = list_entry(pos, struct dx_dirs_inode, list);
+ list_del(&dx_di->list);
+ ocfs2_free(&dx_di);
+ }
+}
+
+static int disable_indexed_dirs(ocfs2_filesys *fs, int flags)
+{
+ errcode_t ret = 0;
+ struct ocfs2_super_block *super = OCFS2_RAW_SB(fs->fs_super);
+ struct dx_dirs_context ctxt;
+ struct tools_progress *prog = NULL;
+
+ if (!ocfs2_supports_indexed_dirs(super)) {
+ verbosef(VL_APP,
+ "Directory indexing feature is not enabled; "
+ "nothing to disable\n");
+ goto out;
+ }
+
+ if (!tools_interact("Disabling the directory indexing feature on "
+ "device \"%s\"? ",
+ fs->fs_devname))
+ goto out;
+
+ prog = tools_progress_start("Disable directory indexing", "no dir idx", 2);
+ if (!prog) {
+ ret = TUNEFS_ET_NO_MEMORY;
+ tcom_err(ret, "while initializing the progress display");
+ goto out;
+ }
+
+ memset(&ctxt, 0, sizeof (struct dx_dirs_context));
+ INIT_LIST_HEAD(&ctxt.inodes);
+ ret = find_indexed_dirs(fs, &ctxt);
+ if (ret) {
+ tcom_err(ret, "while scanning indexed directories");
+ goto out_cleanup;
+ }
+
+ tools_progress_step(prog, 1);
+
+ tunefs_block_signals();
+ ret = clean_indexed_dirs(fs, &ctxt);
+ if (ret) {
+ tcom_err(ret, "while truncate indexed directories");
+ }
+
+ /* We already touched file system, must disable dx dirs flag here.
+ * fsck.ocfs2 will handle the orphan indexed trees. */
+ OCFS2_CLEAR_INCOMPAT_FEATURE(super,
+ OCFS2_FEATURE_INCOMPAT_INDEXED_DIRS);
+ ret = ocfs2_write_super(fs);
+ tunefs_unblock_signals();
+
+ if (ret) {
+ ret = TUNEFS_ET_IO_WRITE_FAILED;
+ tcom_err(ret, "while writing super block");
+ }
+
+ tools_progress_step(prog, 1);
+out_cleanup:
+ release_dx_dirs_context(&ctxt);
+out:
+ if (prog)
+ tools_progress_stop(prog);
+
+ return ret;
+}
+
/*
* TUNEFS_FLAG_ALLOCATION because disabling will want to dealloc
* blocks.
@@ -79,7 +267,7 @@ DEFINE_TUNEFS_FEATURE_INCOMPAT(indexed_dirs,
OCFS2_FEATURE_INCOMPAT_INDEXED_DIRS,
TUNEFS_FLAG_RW | TUNEFS_FLAG_ALLOCATION,
enable_indexed_dirs,
- NULL);
+ disable_indexed_dirs);
#ifdef DEBUG_EXE
int main(int argc, char *argv[])
diff --git a/tunefs.ocfs2/o2ne_err.et b/tunefs.ocfs2/o2ne_err.et
index 20031a5..c2f700b 100644
--- a/tunefs.ocfs2/o2ne_err.et
+++ b/tunefs.ocfs2/o2ne_err.et
@@ -85,4 +85,13 @@ ec TUNEFS_ET_ONLINE_NOT_SUPPORTED,
ec TUNEFS_ET_CLUSTER_SKIPPED,
"Cluster stack initialization was skipped"
+ec TUNEFS_ET_DX_DIRS_SCAN_FAILED,
+ "Scanning inodes for directory indexing failed"
+
+ec TUNEFS_ET_IO_WRITE_FAILED,
+ "Write I/O failed"
+
+ec TUNEFS_ET_DX_DIRS_TRUNCATE_FAILED,
+ "Truncate directory indexed tree failed"
+
end
--
1.7.0.2

View File

@ -0,0 +1,139 @@
From 28f5939111c09de057750fb30ce40ade8bd2b8ef Mon Sep 17 00:00:00 2001
From: Coly Li <coly.li@suse.de>
Date: Sun, 11 Apr 2010 16:10:08 +0800
Subject: [PATCH 11/30] dx_dirs: build indexed trees when enabling indexed-dirs
Previos enable indexed-dirs implementation only set superblock flag,
does not build indexed trees for existed directories.
Tis patch tries to build indexed trees for directories when enable
indexed-dirs.
Signed-off-by: Coly Li <coly.li@suse.de>
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
---
tunefs.ocfs2/feature_indexed_dirs.c | 67 +++++++++++++++++++++++++++++++----
tunefs.ocfs2/o2ne_err.et | 3 ++
2 files changed, 63 insertions(+), 7 deletions(-)
diff --git a/tunefs.ocfs2/feature_indexed_dirs.c b/tunefs.ocfs2/feature_indexed_dirs.c
index e9f87fb..cfa0dd0 100644
--- a/tunefs.ocfs2/feature_indexed_dirs.c
+++ b/tunefs.ocfs2/feature_indexed_dirs.c
@@ -42,11 +42,46 @@ struct dx_dirs_context {
struct tools_progress *prog;
};
+/*
+ * If an indexed-dirs disabled directory has an indexed tree,
+ * this tree is unreliable. it must be truncated and rebuilt.
+ */
+static errcode_t build_dx_dir(ocfs2_filesys *fs, struct ocfs2_dinode *di,
+ void *user_data)
+{
+ errcode_t ret = 0;
+ struct dx_dirs_context *ctxt = (struct dx_dirs_context *)user_data;
+
+ if (!S_ISDIR(di->i_mode))
+ goto bail;
+
+ if (di->i_dyn_features & OCFS2_INDEXED_DIR_FL) {
+ verbosef(VL_APP,
+ "Directory inode %llu already has an indexed tree, "
+ "rebuild the indexed tree.\n", di->i_blkno);
+ ret = ocfs2_dx_dir_truncate(fs, di->i_blkno);
+ if (ret) {
+ ret = TUNEFS_ET_DX_DIRS_TRUNCATE_FAILED;
+ tcom_err(ret, "while rebulid indexed tree");
+ }
+ }
+ ret = ocfs2_dx_dir_build(fs, di->i_blkno);
+ if (ret) {
+ ret = TUNEFS_ET_DX_DIRS_BUILD_FAILED;
+ tcom_err(ret, "while enable indexed-dirs");
+ }
+
+bail:
+ tools_progress_step(ctxt->prog, 1);
+ return ret;
+}
+
static int enable_indexed_dirs(ocfs2_filesys *fs, int flags)
{
errcode_t ret = 0;
struct ocfs2_super_block *super = OCFS2_RAW_SB(fs->fs_super);
- struct tools_progress *prog;
+ struct tools_progress *prog = NULL;
+ struct dx_dirs_context ctxt;
if (ocfs2_supports_indexed_dirs(super)) {
verbosef(VL_APP,
@@ -55,30 +90,48 @@ static int enable_indexed_dirs(ocfs2_filesys *fs, int flags)
goto out;
}
-
if (!tools_interact("Enable the directory indexing feature on "
"device \"%s\"? ",
fs->fs_devname))
goto out;
- prog = tools_progress_start("Enable directory indexing", "dir idx", 1);
+ prog = tools_progress_start("Enable directory indexing", "dir idx", 2);
if (!prog) {
ret = TUNEFS_ET_NO_MEMORY;
tcom_err(ret, "while initializing the progress display");
goto out;
}
+ memset(&ctxt, 0, sizeof(struct dx_dirs_context));
+ ctxt.prog = tools_progress_start("Building indexed trees", "building", 0);
+ if (!ctxt.prog) {
+ ret = TUNEFS_ET_NO_MEMORY;
+ goto out;
+ }
+
OCFS2_SET_INCOMPAT_FEATURE(super,
OCFS2_FEATURE_INCOMPAT_INDEXED_DIRS);
+
tunefs_block_signals();
ret = ocfs2_write_super(fs);
- tunefs_unblock_signals();
- if (ret)
+ if (ret) {
+ ret = TUNEFS_ET_IO_WRITE_FAILED;
tcom_err(ret, "while writing out the superblock");
-
+ goto unblock_out;
+ }
tools_progress_step(prog, 1);
- tools_progress_stop(prog);
+ ret = tunefs_foreach_inode(fs, build_dx_dir, &ctxt);
+ if (ret)
+ tcom_err(ret, "while building indexed trees");
+unblock_out:
+ tunefs_unblock_signals();
+ tools_progress_step(prog, 1);
+ if (ctxt.prog)
+ tools_progress_stop(ctxt.prog);
out:
+ if (prog)
+ tools_progress_stop(prog);
+
return ret;
}
diff --git a/tunefs.ocfs2/o2ne_err.et b/tunefs.ocfs2/o2ne_err.et
index c2f700b..3561d8c 100644
--- a/tunefs.ocfs2/o2ne_err.et
+++ b/tunefs.ocfs2/o2ne_err.et
@@ -94,4 +94,7 @@ ec TUNEFS_ET_IO_WRITE_FAILED,
ec TUNEFS_ET_DX_DIRS_TRUNCATE_FAILED,
"Truncate directory indexed tree failed"
+ec TUNEFS_ET_DX_DIRS_BUILD_FAILED,
+ "Build directory indexed tree failed"
+
end
--
1.7.0.2

View File

@ -0,0 +1,32 @@
From 183b0b3a12396e838dcb9c1e7dc0423eb3a4fbd5 Mon Sep 17 00:00:00 2001
From: Coly Li <coly.li@suse.de>
Date: Sun, 11 Apr 2010 16:10:09 +0800
Subject: [PATCH 12/30] dx_dirs: fix return value of walk_dirblock() when enable metaecc
If there is no error, the return value 'ret' might be used with
undefined initial value. This patch fixes the error by initiating
it to 0.
Reported-by: Vit Pelcak <vpelcak@novell.com>
Signed-off-by: Coly Li <coly.li@suse.de>
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
---
tunefs.ocfs2/feature_metaecc.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/tunefs.ocfs2/feature_metaecc.c b/tunefs.ocfs2/feature_metaecc.c
index c4de8be..799b404 100644
--- a/tunefs.ocfs2/feature_metaecc.c
+++ b/tunefs.ocfs2/feature_metaecc.c
@@ -135,7 +135,7 @@ static errcode_t walk_dirblock(ocfs2_filesys *fs,
struct tunefs_trailer_context *tc,
struct tunefs_trailer_dirblock *db)
{
- errcode_t ret;
+ errcode_t ret = 0;
struct ocfs2_dir_entry *dirent, *prev = NULL;
unsigned int real_rec_len;
unsigned int offset = 0;
--
1.7.0.2

View File

@ -0,0 +1,131 @@
From 947d4450eed4a18299d7b14b828a69533eb4a2ed Mon Sep 17 00:00:00 2001
From: Coly Li <coly.li@suse.de>
Date: Sun, 11 Apr 2010 16:10:10 +0800
Subject: [PATCH 13/30] dx_dirs: try to install dir trailers when enable indexed-dirs
If metaecc feature is not enabled, previuos indexed-dirs patches in
ocfs2-tools does not install dir trailers and move the dir entries which
lie in the trailer area. This patch tries to install dir trailers when
enable indexed-dirs feature.
Signed-off-by: Coly Li <coly.li@suse.de>
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
---
tunefs.ocfs2/feature_indexed_dirs.c | 8 ++++++++
tunefs.ocfs2/feature_metaecc.c | 25 +++----------------------
tunefs.ocfs2/libocfs2ne.h | 25 +++++++++++++++++++++++++
tunefs.ocfs2/o2ne_err.et | 3 +++
4 files changed, 39 insertions(+), 22 deletions(-)
diff --git a/tunefs.ocfs2/feature_indexed_dirs.c b/tunefs.ocfs2/feature_indexed_dirs.c
index cfa0dd0..c26780e 100644
--- a/tunefs.ocfs2/feature_indexed_dirs.c
+++ b/tunefs.ocfs2/feature_indexed_dirs.c
@@ -65,6 +65,14 @@ static errcode_t build_dx_dir(ocfs2_filesys *fs, struct ocfs2_dinode *di,
tcom_err(ret, "while rebulid indexed tree");
}
}
+
+ ret = tunefs_install_dir_trailer(fs, di, NULL);
+ if (ret) {
+ ret = TUNEFS_ET_INSTALL_DIR_TRAILER_FAILED;
+ tcom_err(ret, "while enable indexed-dirs");
+ goto bail;
+ }
+
ret = ocfs2_dx_dir_build(fs, di->i_blkno);
if (ret) {
ret = TUNEFS_ET_DX_DIRS_BUILD_FAILED;
diff --git a/tunefs.ocfs2/feature_metaecc.c b/tunefs.ocfs2/feature_metaecc.c
index 799b404..e6b48b5 100644
--- a/tunefs.ocfs2/feature_metaecc.c
+++ b/tunefs.ocfs2/feature_metaecc.c
@@ -68,25 +68,6 @@ struct tunefs_trailer_dirblock {
struct ocfs2_dir_entry *db_last;
};
-/* A directory inode we're adding trailers to */
-struct tunefs_trailer_context {
- struct list_head d_list;
- uint64_t d_blkno; /* block number of the dir */
- struct ocfs2_dinode *d_di; /* The directory's inode */
- struct list_head d_dirblocks; /* List of its dirblocks */
- uint64_t d_bytes_needed; /* How many new bytes will
- cover the dirents we are moving
- to make way for trailers */
- uint64_t d_blocks_needed; /* How many blocks covers
- d_bytes_needed */
- char *d_new_blocks; /* Buffer of new blocks to fill */
- char *d_cur_block; /* Which block we're filling in
- d_new_blocks */
- struct ocfs2_dir_entry *d_next_dirent; /* Next dentry to use */
- errcode_t d_err; /* Any processing error during
- iteration of the directory */
-};
-
static void tunefs_trailer_context_free(struct tunefs_trailer_context *tc)
{
struct tunefs_trailer_dirblock *db;
@@ -529,9 +510,9 @@ out:
}
-static errcode_t tunefs_install_dir_trailer(ocfs2_filesys *fs,
- struct ocfs2_dinode *di,
- struct tunefs_trailer_context *tc)
+errcode_t tunefs_install_dir_trailer(ocfs2_filesys *fs,
+ struct ocfs2_dinode *di,
+ struct tunefs_trailer_context *tc)
{
errcode_t ret = 0;
struct tunefs_trailer_context *our_tc = NULL;
diff --git a/tunefs.ocfs2/libocfs2ne.h b/tunefs.ocfs2/libocfs2ne.h
index a8e1e5e..18380be 100644
--- a/tunefs.ocfs2/libocfs2ne.h
+++ b/tunefs.ocfs2/libocfs2ne.h
@@ -281,5 +281,30 @@ errcode_t tunefs_feature_run(ocfs2_filesys *master_fs,
int tunefs_feature_main(int argc, char *argv[], struct tunefs_feature *feat);
int tunefs_op_main(int argc, char *argv[], struct tunefs_operation *op);
+/* A directory inode we're adding trailers to */
+struct tunefs_trailer_context {
+ struct list_head d_list;
+ uint64_t d_blkno; /* block number of the dir */
+ struct ocfs2_dinode *d_di; /* The directory's inode */
+ struct list_head d_dirblocks; /* List of its dirblocks */
+ uint64_t d_bytes_needed; /* How many new bytes will
+ cover the dirents we are moving
+ to make way for trailers */
+ uint64_t d_blocks_needed; /* How many blocks covers
+ d_bytes_needed */
+ char *d_new_blocks; /* Buffer of new blocks to fill */
+ char *d_cur_block; /* Which block we're filling in
+ d_new_blocks */
+ struct ocfs2_dir_entry *d_next_dirent; /* Next dentry to use */
+ errcode_t d_err; /* Any processing error during
+ iteration of the directory */
+};
+
+/*
+ * called from feature_metaecc.c and feature_indexed_dirs.c
+ * to install dir trailers
+ */
+errcode_t tunefs_install_dir_trailer(ocfs2_filesys *fs, struct ocfs2_dinode *di,
+ struct tunefs_trailer_context *tc);
#endif /* _LIBTUNEFS_H */
diff --git a/tunefs.ocfs2/o2ne_err.et b/tunefs.ocfs2/o2ne_err.et
index 3561d8c..955c338 100644
--- a/tunefs.ocfs2/o2ne_err.et
+++ b/tunefs.ocfs2/o2ne_err.et
@@ -97,4 +97,7 @@ ec TUNEFS_ET_DX_DIRS_TRUNCATE_FAILED,
ec TUNEFS_ET_DX_DIRS_BUILD_FAILED,
"Build directory indexed tree failed"
+ec TUNEFS_ET_INSTALL_DIR_TRAILER_FAILED,
+ "Install directory trailer failed"
+
end
--
1.7.0.2

View File

@ -0,0 +1,32 @@
From 0fe34f26335f1d2f10550b2e12f65f6f24f39a6f Mon Sep 17 00:00:00 2001
From: Coly Li <coly.li@suse.de>
Date: Sun, 11 Apr 2010 16:10:11 +0800
Subject: [PATCH 14/30] dx_dirs: add an initial man page entry for indexed-dirs
This patch add an initial man page entry for indexed-dirs feature
string.
Signed-off-by: Coly Li <coly.li@suse.de>
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
---
mkfs.ocfs2/mkfs.ocfs2.8.in | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/mkfs.ocfs2/mkfs.ocfs2.8.in b/mkfs.ocfs2/mkfs.ocfs2.8.in
index c7a7888..a148133 100644
--- a/mkfs.ocfs2/mkfs.ocfs2.8.in
+++ b/mkfs.ocfs2/mkfs.ocfs2.8.in
@@ -175,6 +175,10 @@ and number of inodes (files, directories, symbolic links) each group owns. It is
to limit the maximum amount of space or inodes user can have. See a documentation of
quota-tools package for more details.
.RE
+.TP
+\fBindexed-dirs\fR
+Enable directory indexing support. With this feature enabled, the file system creates indexed tree for non-inline directory entries. For large scale directories, directory entry lookup perfromance from the indexed tree is faster then from the legacy directory blocks.
+.RE
.TP
\fB\-\-fs\-feature\-level=\fR\fR\fIfeature\-level\fR
--
1.7.0.2

View File

@ -0,0 +1,48 @@
From ed44744701bd4eeaf5ee0fcce9190cdf36b5b21c Mon Sep 17 00:00:00 2001
From: Mark Fasheh <mfasheh@suse.com>
Date: Mon, 19 Apr 2010 16:25:48 -0700
Subject: [PATCH 15/30] fsck.ocfs2: prompt before truncating an invalid dir index
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
---
fsck.ocfs2/fsck.ocfs2.checks.8.in | 6 ++++++
fsck.ocfs2/pass2.c | 6 +++++-
2 files changed, 11 insertions(+), 1 deletions(-)
diff --git a/fsck.ocfs2/fsck.ocfs2.checks.8.in b/fsck.ocfs2/fsck.ocfs2.checks.8.in
index 05561ae..5cda023 100644
--- a/fsck.ocfs2/fsck.ocfs2.checks.8.in
+++ b/fsck.ocfs2/fsck.ocfs2.checks.8.in
@@ -1055,6 +1055,12 @@ but fsck has already found quota limits for this user / group.
Answering yes will use new values of limits for the user / group.
+.SS "IV_DX_TREE"
+A directory index was found on an inode but that feature is not enabled on the
+file system.
+
+Answering yes will truncate the invalid index.
+
.SH "SEE ALSO"
.BR fsck.ocfs2(8)
diff --git a/fsck.ocfs2/pass2.c b/fsck.ocfs2/pass2.c
index 58efcd4..b999761 100644
--- a/fsck.ocfs2/pass2.c
+++ b/fsck.ocfs2/pass2.c
@@ -874,7 +874,11 @@ next:
if ((!ocfs2_supports_indexed_dirs(OCFS2_RAW_SB(dd->fs->fs_super)))&&
di->i_dyn_features & OCFS2_INDEXED_DIR_FL ) {
/* ignore the return value */
- ocfs2_dx_dir_truncate(dd->fs, dbe->e_ino);
+ if (prompt(dd->ost, PY, PR_IV_DX_TREE, "A directory index was "
+ "found on inode %"PRIu64" but the indexing feature "
+ "is not set on the fs. Truncate the invalid index?",
+ dbe->e_ino))
+ ocfs2_dx_dir_truncate(dd->fs, dbe->e_ino);
}
out:
--
1.7.0.2

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,30 @@
From e618ad9a6cafae5351f87ae0601d3b16ec9af96a Mon Sep 17 00:00:00 2001
From: Mark Fasheh <mfasheh@suse.com>
Date: Mon, 19 Apr 2010 21:36:37 -0700
Subject: [PATCH 17/30] dx_dirs: add check for invalid slot in ocfs2_new_dx_root()
This can happen in the case of a system inode, such as the root or orphan
directories.
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
---
libocfs2/alloc.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/libocfs2/alloc.c b/libocfs2/alloc.c
index 84f3b05..7f85a34 100644
--- a/libocfs2/alloc.c
+++ b/libocfs2/alloc.c
@@ -658,6 +658,9 @@ errcode_t ocfs2_new_dx_root(ocfs2_filesys *fs,
goto out;
slot = di->i_suballoc_slot;
+ if (slot == (uint16_t)OCFS2_INVALID_SLOT)
+ slot = 0;
+
ret = ocfs2_load_allocator(fs, EXTENT_ALLOC_SYSTEM_INODE,
slot, &fs->fs_eb_allocs[slot]);
if (ret)
--
1.7.0.2

View File

@ -0,0 +1,137 @@
From 88d139c22a91b17ff451a50e37d002d8714748f3 Mon Sep 17 00:00:00 2001
From: Mark Fasheh <mfasheh@suse.com>
Date: Mon, 19 Apr 2010 22:26:47 -0700
Subject: [PATCH 18/30] mkfs.ocfs2: create root and orphan directories as indexed
If the indexed dirs feature is enabled but the inline directories feature is
for some reason disabled, we'll create sub-optimal (non-indexed) root and
orphan directories. It's easy however at the end of mkfs.ocfs2 to simply
index these.
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
---
mkfs.ocfs2/mkfs.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++----
mkfs.ocfs2/mkfs.h | 1 +
2 files changed, 62 insertions(+), 6 deletions(-)
diff --git a/mkfs.ocfs2/mkfs.c b/mkfs.ocfs2/mkfs.c
index b43a9ba..5507872 100644
--- a/mkfs.ocfs2/mkfs.c
+++ b/mkfs.ocfs2/mkfs.c
@@ -82,6 +82,7 @@ static AllocGroup * initialize_alloc_group(State *s, const char *name,
uint64_t blkno,
uint16_t chain, uint16_t cpg,
uint16_t bpc);
+static void index_system_dirs(State *s, ocfs2_filesys *fs);
static void create_lost_found_dir(State *s, ocfs2_filesys *fs);
static void format_journals(State *s, ocfs2_filesys *fs);
static void format_slotmap(State *s, ocfs2_filesys *fs);
@@ -436,12 +437,6 @@ static void finish_normal_format(State *s)
printf("done\n");
if (!s->quiet)
- printf("Writing lost+found: ");
- create_lost_found_dir(s, fs);
- if (!s->quiet)
- printf("done\n");
-
- if (!s->quiet)
printf("Formatting quota files: ");
format_quota_files(s, fs);
@@ -449,6 +444,24 @@ static void finish_normal_format(State *s)
if (!s->quiet)
printf("done\n");
+ if (s->dx_dirs && !s->inline_data) {
+ /*
+ * We want to do this after quota, but before adding
+ * any new entries to directories.
+ */
+ if (!s->quiet)
+ printf("Indexing system directories: ");
+ index_system_dirs(s, fs);
+ if (!s->quiet)
+ printf("done\n");
+ }
+
+ if (!s->quiet)
+ printf("Writing lost+found: ");
+ create_lost_found_dir(s, fs);
+ if (!s->quiet)
+ printf("done\n");
+
ocfs2_close(fs);
}
@@ -1085,6 +1098,10 @@ get_state(int argc, char **argv)
s->no_backup_super = 0;
else
s->no_backup_super = 1;
+ if (s->feature_flags.opt_incompat & OCFS2_FEATURE_INCOMPAT_INDEXED_DIRS)
+ s->dx_dirs = 1;
+ else
+ s->dx_dirs = 0;
/* Here if the user set these flags explicitly, we will use them and
@@ -2751,6 +2768,44 @@ clear_both_ends(State *s)
return ;
}
+static void index_system_dirs(State *s, ocfs2_filesys *fs)
+{
+ errcode_t ret;
+ int i, num_slots = OCFS2_RAW_SB(fs->fs_super)->s_max_slots;
+ uint64_t orphan_dir_blkno;
+
+
+ /* Start with the root directory */
+ ret = ocfs2_dx_dir_build(fs, fs->fs_root_blkno);
+ if (ret) {
+ com_err(s->progname, ret, "while indexing root directory");
+ goto bail;
+ }
+
+ for (i = 0; i < num_slots; i++) {
+ ret = ocfs2_lookup_system_inode(fs, ORPHAN_DIR_SYSTEM_INODE,
+ i, &orphan_dir_blkno);
+ if (ret) {
+ com_err(s->progname, ret,
+ "while looking up orphan dir %d for indexing",
+ i);
+ goto bail;
+ }
+
+ ret = ocfs2_dx_dir_build(fs, orphan_dir_blkno);
+ if (ret) {
+ com_err(s->progname, ret, "while indexing root directory");
+ goto bail;
+ }
+ }
+
+ return;
+
+bail:
+ clear_both_ends(s);
+ exit(1);
+}
+
static void create_lost_found_dir(State *s, ocfs2_filesys *fs)
{
errcode_t ret;
diff --git a/mkfs.ocfs2/mkfs.h b/mkfs.ocfs2/mkfs.h
index b702f00..c3aecd6 100644
--- a/mkfs.ocfs2/mkfs.h
+++ b/mkfs.ocfs2/mkfs.h
@@ -188,6 +188,7 @@ struct _State {
int mount;
int no_backup_super;
int inline_data;
+ int dx_dirs;
int dry_run;
uint32_t blocksize;
--
1.7.0.2

View File

@ -0,0 +1,26 @@
From 912f3e698ed20eb14daad38ef79b106a30d39a02 Mon Sep 17 00:00:00 2001
From: Mark Fasheh <mfasheh@suse.com>
Date: Tue, 20 Apr 2010 10:19:54 -0700
Subject: [PATCH 19/30] libocfs2: fix flag check in ocfs2_init_dir()
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
---
libocfs2/expanddir.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/libocfs2/expanddir.c b/libocfs2/expanddir.c
index ec05b74..eb18260 100644
--- a/libocfs2/expanddir.c
+++ b/libocfs2/expanddir.c
@@ -238,7 +238,7 @@ errcode_t ocfs2_init_dir(ocfs2_filesys *fs,
* directory to extent in ocfs2_expand_dir()
*/
if (ocfs2_supports_indexed_dirs(OCFS2_RAW_SB(fs->fs_super)) &&
- (!cinode->ci_inode->i_dyn_features & OCFS2_INLINE_DATA_FL)) {
+ !(cinode->ci_inode->i_dyn_features & OCFS2_INLINE_DATA_FL)) {
ret = ocfs2_dx_dir_build(fs, dir);
if (ret)
goto bail;
--
1.7.0.2

View File

@ -0,0 +1,40 @@
From 30a19b42c6da181fa3f96123041fb20e69d065d9 Mon Sep 17 00:00:00 2001
From: Mark Fasheh <mfasheh@suse.com>
Date: Tue, 20 Apr 2010 10:20:24 -0700
Subject: [PATCH 20/30] libocfs2: fix ocfs2_init_dir() to retain indexed flag
We were re-using the out of date 'cached inode' later in the function after
ocfs2_dx_dir_build() (which updates and writes out the inode internally).
As a result, ocfs2_init_dir() was accidentally clearing
OCFS2_INDEXED_DIR_FL. Fix this by refreshing the cache after the call to
ocfs2_dx_dir_build().
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
---
libocfs2/expanddir.c | 9 +++++++++
1 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/libocfs2/expanddir.c b/libocfs2/expanddir.c
index eb18260..a81cfbe 100644
--- a/libocfs2/expanddir.c
+++ b/libocfs2/expanddir.c
@@ -242,6 +242,15 @@ errcode_t ocfs2_init_dir(ocfs2_filesys *fs,
ret = ocfs2_dx_dir_build(fs, dir);
if (ret)
goto bail;
+
+ /*
+ * Re-read the 'cached inode' as ocfs2_dx_dir_build()
+ * may have written out changes which won't be
+ * reflected in our copy.
+ */
+ ret = ocfs2_read_cached_inode(fs, dir, &cinode);
+ if (ret)
+ goto bail;
}
/* set link count of the parent */
--
1.7.0.2

View File

@ -0,0 +1,92 @@
From 4c1cf61779ee71c828134d956f5779e272a3195e Mon Sep 17 00:00:00 2001
From: Mark Fasheh <mfasheh@suse.com>
Date: Fri, 23 Apr 2010 23:09:05 -0700
Subject: [PATCH 21/30] fsck.ocfs2: verify dirent -> dx entry linkages
During pass2 we can trivially do a lookup on dirents while walking the
directory tree. This will help us make sure that an index entry exists for
each dirent. If an entry is not found, the users is prompted and the parent
directory will be marked for an index rebuild.
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
---
fsck.ocfs2/fsck.ocfs2.checks.8.in | 7 +++++++
fsck.ocfs2/pass2.c | 37 +++++++++++++++++++++++++++++++++++++
2 files changed, 44 insertions(+), 0 deletions(-)
diff --git a/fsck.ocfs2/fsck.ocfs2.checks.8.in b/fsck.ocfs2/fsck.ocfs2.checks.8.in
index 5cda023..cfbb12e 100644
--- a/fsck.ocfs2/fsck.ocfs2.checks.8.in
+++ b/fsck.ocfs2/fsck.ocfs2.checks.8.in
@@ -1061,6 +1061,13 @@ file system.
Answering yes will truncate the invalid index.
+.SS "DX_LOOKUP_FAILED"
+A directory entry is missing an entry in the directory index. Not
+found in directory index. The missing index entry will cause lookups
+on this name to fail.
+
+Answering yes will rebuild the directory index, restoring the missing entry.
+
.SH "SEE ALSO"
.BR fsck.ocfs2(8)
diff --git a/fsck.ocfs2/pass2.c b/fsck.ocfs2/pass2.c
index b999761..e03bd4e 100644
--- a/fsck.ocfs2/pass2.c
+++ b/fsck.ocfs2/pass2.c
@@ -648,6 +648,39 @@ out:
return ret;
}
+static errcode_t fix_dirent_index(o2fsck_dirblock_entry *dbe,
+ struct dirblock_data *dd,
+ struct ocfs2_dir_entry *dirent,
+ unsigned int *flags)
+{
+ errcode_t ret = 0;
+ struct ocfs2_dinode *di = (struct ocfs2_dinode *)dd->inoblock_buf;
+ uint64_t ino;
+
+ if (!ocfs2_supports_indexed_dirs(OCFS2_RAW_SB(dd->fs->fs_super)))
+ goto out;
+
+ if (di->i_dyn_features & OCFS2_INDEXED_DIR_FL) {
+ ret = ocfs2_lookup(dd->fs, dbe->e_ino, dirent->name,
+ dirent->name_len, NULL, &ino);
+ if (ret) {
+ if (ret != OCFS2_ET_FILE_NOT_FOUND)
+ goto out;
+ ret = 0;
+
+ if (prompt(dd->ost, PY, PR_DX_LOOKUP_FAILED,
+ "Directory inode %"PRIu64" is missing "
+ "an index entry for child inode %"PRIu64
+ "\n. Repair this by rebuilding the "
+ "directory index?", dbe->e_ino, ino))
+ *flags |= OCFS2_DIRENT_CHANGED;
+ goto out;
+ }
+ }
+out:
+ return ret;
+}
+
static int corrupt_dirent_lengths(struct ocfs2_dir_entry *dirent, int left)
{
if ((dirent->rec_len >= OCFS2_DIR_REC_LEN(1)) &&
@@ -805,6 +838,10 @@ static unsigned pass2_dir_block_iterate(o2fsck_dirblock_entry *dbe,
if (dirent->inode == 0)
goto next;
+ ret = fix_dirent_index(dbe, dd, dirent, &ret_flags);
+ if (ret)
+ goto out;
+
verbosef("dirent %.*s refs ino %"PRIu64"\n", dirent->name_len,
dirent->name, (uint64_t)dirent->inode);
o2fsck_icount_delta(dd->ost->ost_icount_refs, dirent->inode, 1);
--
1.7.0.2

View File

@ -0,0 +1,106 @@
From 24b059e1e75a0ff5dabb8a6dfdc09e82d488c244 Mon Sep 17 00:00:00 2001
From: Coly Li <coly.li@suse.de>
Date: Mon, 26 Apr 2010 22:34:27 +0800
Subject: [PATCH 22/30] dx_dirs: stop iterate dir entries for I/O error
Callback dx_iterator() may encounter an I/O error when calling
ocfs2_read_dx_leaf(). The caller of dx_iterator is extent_iterate_el(),
which does not accept error code other than OCFS2_EXTENT_ERROR and
OCFS2_EXTENT_ABORT. The result is, dir entries iteration can not stop
if there is an I/O error happens in dx_iterator().
This patch add 'errcode_t err' member to struct dx_iterator_data, if
error returned from ocfs2_read_dx_leaf(), the error code will be
stored here, then dx_iterator() returns OCFS2_EXTENT_ERROR to make
extent_iterate_el() quit.
Thanks to Tao Ma for catching this error.
Signed-off-by: Coly Li <coly.li@suse.de>
Cc: Mark Fasheh <mfasheh@suse.com>
Cc: Tao Ma <tao.ma@oracle.com>
---
libocfs2/dir_iterate.c | 22 +++++++++++++++-------
libocfs2/extents.c | 2 +-
2 files changed, 16 insertions(+), 8 deletions(-)
diff --git a/libocfs2/dir_iterate.c b/libocfs2/dir_iterate.c
index 8a3f5a9..d044bb8 100644
--- a/libocfs2/dir_iterate.c
+++ b/libocfs2/dir_iterate.c
@@ -320,6 +320,7 @@ struct dx_iterator_data {
void *dx_priv_data;
char *leaf_buf;
struct ocfs2_dx_root_block *dx_root;
+ errcode_t err;
};
static int dx_iterator(ocfs2_filesys *fs,
@@ -330,7 +331,7 @@ static int dx_iterator(ocfs2_filesys *fs,
int ref_recno,
void *priv_data)
{
- int ret, i;
+ int err, i;
struct ocfs2_dx_leaf *dx_leaf;
struct dx_iterator_data *iter = priv_data;
uint64_t blkno, count;
@@ -339,9 +340,11 @@ static int dx_iterator(ocfs2_filesys *fs,
blkno = rec->e_blkno;
for (i = 0; i < count; i++) {
- ret = ocfs2_read_dx_leaf(fs, blkno, iter->leaf_buf);
- if (ret)
- return ret;
+ err = ocfs2_read_dx_leaf(fs, blkno, iter->leaf_buf);
+ if (err) {
+ iter->err = err;
+ return OCFS2_EXTENT_ERROR;
+ }
dx_leaf = (struct ocfs2_dx_leaf *)iter->leaf_buf;
iter->dx_func(fs, &dx_leaf->dl_list, iter->dx_root, dx_leaf,
@@ -387,8 +390,7 @@ extern errcode_t ocfs2_dx_entries_iterate(ocfs2_filesys *fs,
dx_root = (struct ocfs2_dx_root_block *)buf;
if (dx_root->dr_flags & OCFS2_DX_FLAG_INLINE) {
- func(fs, &dx_root->dr_entries, dx_root, NULL, priv_data);
- ret = 0;
+ ret = func(fs, &dx_root->dr_entries, dx_root, NULL, priv_data);
goto out;
}
@@ -404,10 +406,16 @@ extern errcode_t ocfs2_dx_entries_iterate(ocfs2_filesys *fs,
data.dx_priv_data = priv_data;
data.leaf_buf = leaf_buf;
data.dx_root = dx_root;
+ data.err = 0;
ret = ocfs2_extent_iterate_dx_root(fs, dx_root,
OCFS2_EXTENT_FLAG_DATA_ONLY, eb_buf,
dx_iterator, &data);
-
+ /* dx_iterator may set the error code for non-extents-related
+ * errors. If the error code is set by dx_iterator, no matter
+ * what ocfs2_extent_iterate_dx_root() returns, we should take
+ * data.err as retured error code. */
+ if (data.err)
+ ret = data.err;
out:
if (buf)
ocfs2_free(&buf);
diff --git a/libocfs2/extents.c b/libocfs2/extents.c
index 8c322b1..bb233f0 100644
--- a/libocfs2/extents.c
+++ b/libocfs2/extents.c
@@ -470,7 +470,7 @@ errcode_t ocfs2_extent_iterate_inode(ocfs2_filesys *fs,
uint64_t ref_blkno,
int ref_recno,
void *priv_data),
- void *priv_data)
+ void *priv_data)
{
int i;
int iret = 0;
--
1.7.0.2

View File

@ -0,0 +1,40 @@
From d4bbb81a8e6870155eb939a1f9d6def456fa3b91 Mon Sep 17 00:00:00 2001
From: Coly Li <coly.li@suse.de>
Date: Mon, 26 Apr 2010 22:35:02 +0800
Subject: [PATCH 23/30] dx_dirs: check callback iter->dx_func() return value in dx_iterator()
This patch makes dx_iterator() check returned value of callback
iter->dx_func(). If an error returned from the callback, dx_iterator()
returns OCFS2_EXTENT_ERROR to stop the iteration.
Thanks to Tao Ma for catching the error.
Signed-off-by: Coly Li <coly.li@suse.de>
Cc: Mark Fasheh <mfasheh@suse.com>
Cc: Tao Ma <tao.ma@oracle.com>
---
libocfs2/dir_iterate.c | 7 ++++++-
1 files changed, 6 insertions(+), 1 deletions(-)
diff --git a/libocfs2/dir_iterate.c b/libocfs2/dir_iterate.c
index d044bb8..9f2ff7e 100644
--- a/libocfs2/dir_iterate.c
+++ b/libocfs2/dir_iterate.c
@@ -347,8 +347,13 @@ static int dx_iterator(ocfs2_filesys *fs,
}
dx_leaf = (struct ocfs2_dx_leaf *)iter->leaf_buf;
- iter->dx_func(fs, &dx_leaf->dl_list, iter->dx_root, dx_leaf,
+ err = iter->dx_func(fs, &dx_leaf->dl_list, iter->dx_root, dx_leaf,
iter->dx_priv_data);
+ /* callback dx_func() is defined by users, the return value does not
+ * follow libocfs2 error codes. Don't touch iter->err and just stop
+ * the iteration here.*/
+ if (err)
+ return OCFS2_EXTENT_ERROR;
blkno++;
}
--
1.7.0.2

View File

@ -0,0 +1,45 @@
From c74da336c1e4eb2fac311c9e6ea8ef8fe9b0a6c1 Mon Sep 17 00:00:00 2001
From: Coly Li <coly.li@suse.de>
Date: Mon, 26 Apr 2010 22:35:27 +0800
Subject: [PATCH 24/30] dx_dirs: remove unncessary return value assignment
This patch removes unnecessary return value assigned in
ocfs2_dx_entries_iterate() and ocfs2_dx_frees_iterate().
Thanks for Tao Ma for catching this.
Signed-off-by: Coly Li <coly.li@suse.de>
Cc: Mark Fasheh <mfasheh@suse.com>
Cc: Tao Ma <tao.ma@oracle.com>
---
libocfs2/dir_iterate.c | 3 ---
1 files changed, 0 insertions(+), 3 deletions(-)
diff --git a/libocfs2/dir_iterate.c b/libocfs2/dir_iterate.c
index 9f2ff7e..835305a 100644
--- a/libocfs2/dir_iterate.c
+++ b/libocfs2/dir_iterate.c
@@ -378,7 +378,6 @@ extern errcode_t ocfs2_dx_entries_iterate(ocfs2_filesys *fs,
struct dx_iterator_data data;
if (!S_ISDIR(dir->i_mode) && !ocfs2_dir_indexed(dir)) {
- ret = 0;
goto out;
}
@@ -448,12 +447,10 @@ extern errcode_t ocfs2_dx_frees_iterate(ocfs2_filesys *fs,
struct ocfs2_dir_block_trailer *trailer;
if (!S_ISDIR(dir->i_mode) || !(ocfs2_dir_indexed(dir))) {
- ret = 0;
goto out;
}
if (dx_root->dr_flags & OCFS2_DX_FLAG_INLINE) {
- ret = 0;
goto out;
}
--
1.7.0.2

View File

@ -0,0 +1,33 @@
From 1e82ab1d1407d4578eda91214e843b5433a92d6f Mon Sep 17 00:00:00 2001
From: Coly Li <coly.li@suse.de>
Date: Mon, 26 Apr 2010 22:35:58 +0800
Subject: [PATCH 25/30] dx_dirs: unifiy feature string of indexed-dirs
This patch changes the indexed-dirs fn_name of ocfs2_feature_name array
from IndexedDirs to indexed-dirs. Which unitifies fn_name displayed in
debugfs.ocfs2 to feature string 'indexed-dirs' used in mkfs.ocfs2 and
tunefs.ocfs2.
Signed-off-by: Coly Li <coly.li@suse.de>
Cc: Mark Fasheh <mfasheh@suse.com>
Cc: Tao Ma <tao.ma@oracle.com>
---
libocfs2/feature_string.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/libocfs2/feature_string.c b/libocfs2/feature_string.c
index 9f395c6..83fec9a 100644
--- a/libocfs2/feature_string.c
+++ b/libocfs2/feature_string.c
@@ -254,7 +254,7 @@ static struct feature_name ocfs2_feature_names[] = {
.fn_flag = {0, OCFS2_FEATURE_INCOMPAT_XATTR, 0},
},
{
- .fn_name = "IndexedDirs",
+ .fn_name = "indexed-dirs",
.fn_flag = {0, OCFS2_FEATURE_INCOMPAT_INDEXED_DIRS, 0},
},
{
--
1.7.0.2

View File

@ -0,0 +1,33 @@
From a3a8830774c41b90285d77ccc04a035c944080e9 Mon Sep 17 00:00:00 2001
From: Coly Li <coly.li@suse.de>
Date: Mon, 26 Apr 2010 22:36:38 +0800
Subject: [PATCH 26/30] dx_dirs: Improve information displayed by dump_dx_root()
If dr->dr_suballoc_slot is OCFS2_INVALID_SLOT (which should not happen),
should not display "Global", because there is not "Global" conception
for dx root allocation slot. This patch fixes the display by
"Invalid Slot".
Signed-off-by: Coly Li <coly.li@suse.de>
Cc: Mark Fasheh <mfasheh@suse.com>
Cc: Tao Ma <tao.ma@oracle.com>
---
debugfs.ocfs2/dump.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/debugfs.ocfs2/dump.c b/debugfs.ocfs2/dump.c
index d55fc0e..6ad202c 100644
--- a/debugfs.ocfs2/dump.c
+++ b/debugfs.ocfs2/dump.c
@@ -593,7 +593,7 @@ void dump_dx_root(FILE *out, struct ocfs2_dx_root_block *dr)
(uint64_t)dr->dr_dir_blkno);
if (dr->dr_suballoc_slot == (uint16_t)OCFS2_INVALID_SLOT)
- strcpy(tmp_str, "Global");
+ strcpy(tmp_str, "Invalid Slot");
else
sprintf(tmp_str, "%d", dr->dr_suballoc_slot);
fprintf(out, "\tSub Alloc Slot: %s Sub Alloc Bit: %u "
--
1.7.0.2

View File

@ -0,0 +1,103 @@
From cb9471a5f73c69858d9dd35ea90b86476e65e4ca Mon Sep 17 00:00:00 2001
From: Coly Li <coly.li@suse.de>
Date: Mon, 26 Apr 2010 22:37:05 +0800
Subject: [PATCH 27/30] dx_dirs: stop iteration of dir trailer initialization for I/O error
Callback dir_trailer_func() may encounter malloc or I/O error, these
errors can not return to its caller directly. This patch add a member
'errcode_t err' to struct trailer_ctxt, which can catch the error. By
this fix, dir_trailer_func() can return OCFS2_EXTENT_ERROR to stop dir
iteration immediately and can return the REAL error as well.
Thanks to Tao Ma catches this error.
Signed-off-by: Coly Li <coly.li@suse.de>
Cc: Mark Fasheh <mfasheh@suse.com>
Cc: Tao Ma <tao.ma@oracle.com>
---
libocfs2/dir_indexed.c | 37 +++++++++++++++++++++++++++++--------
1 files changed, 29 insertions(+), 8 deletions(-)
diff --git a/libocfs2/dir_indexed.c b/libocfs2/dir_indexed.c
index 9cae3d0..5f3db95 100644
--- a/libocfs2/dir_indexed.c
+++ b/libocfs2/dir_indexed.c
@@ -121,6 +121,7 @@ int ocfs2_find_max_rec_len(ocfs2_filesys *fs, char *buf)
struct trailer_ctxt {
struct ocfs2_dx_root_block *dx_root;
struct ocfs2_dinode *di;
+ errcode_t err;
};
/* make sure the space for trailer is reserved */
@@ -170,8 +171,8 @@ static int dir_trailer_func(ocfs2_filesys *fs,
struct ocfs2_dinode *di = ctxt->di;
struct ocfs2_dx_root_block *dx_root = ctxt->dx_root;
struct ocfs2_dir_block_trailer *trailer;
- int max_rec_len = 0;
- errcode_t ret = 0;
+ int max_rec_len = 0, ret = 0;
+ errcode_t err;
char *blk = NULL;
ret = ocfs2_malloc_block(fs->fs_io, &blk);
@@ -180,12 +181,20 @@ static int dir_trailer_func(ocfs2_filesys *fs,
/* here we don't trust trailer, cannot use
* ocfs2_read_dir_block() */
- ret = ocfs2_read_blocks(fs, blkno, 1, blk);
- if (ret)
+ err = ocfs2_read_blocks(fs, blkno, 1, blk);
+ if (err) {
+ ctxt->err = err;
+ ret = OCFS2_EXTENT_ERROR;
goto out;
- ret = ocfs2_check_dir_trailer_space(fs, di, blkno, blk);
- if (ret)
+ }
+
+ err = ocfs2_check_dir_trailer_space(fs, di, blkno, blk);
+ if (err) {
+ ctxt->err = err;
+ ret = OCFS2_EXTENT_ERROR;
goto out;
+ }
+
ocfs2_init_dir_trailer(fs, di, blkno, blk);
max_rec_len = ocfs2_find_max_rec_len(fs, blk);
trailer = ocfs2_dir_trailer_from_block(fs, blk);
@@ -198,7 +207,12 @@ static int dir_trailer_func(ocfs2_filesys *fs,
/* comput trailer->db_check here, after writes out,
* trailer is trustable */
- ret = ocfs2_write_dir_block(fs, di, blkno, blk);
+ err = ocfs2_write_dir_block(fs, di, blkno, blk);
+ if (err) {
+ ctxt->err = err;
+ ret = OCFS2_EXTENT_ERROR;
+ }
+
out:
if (blk)
ocfs2_free(&blk);
@@ -219,9 +233,16 @@ static errcode_t ocfs2_init_dir_trailers(ocfs2_filesys *fs,
ctxt.di = di;
ctxt.dx_root = dx_root;
-
+ ctxt.err = 0;
ret = ocfs2_block_iterate_inode(fs, di,
0, dir_trailer_func, &ctxt);
+
+ /* callback dir_trailer_func() may have error which can not
+ * return to its caller directly. If dir_trailer_func() sets
+ * error in ctxt.err, we should take this REAL error other
+ * than the value returned by ocfs2_block_iterate_inode(). */
+ if (ctxt.err)
+ ret = ctxt.err;
out:
return ret;
}
--
1.7.0.2

View File

@ -0,0 +1,141 @@
From 1f49857cc5fa914ac0d3577f841b398421ca01a0 Mon Sep 17 00:00:00 2001
From: Coly Li <coly.li@suse.de>
Date: Mon, 26 Apr 2010 22:37:32 +0800
Subject: [PATCH 28/30] dx_dirs: stop dx insert iteration for callback error
Callback ocfs2_dx_dir_insert() may encounter memory alloc or I/O error.
These kind of errors can not return to caller of the callback directly,
so the dir block iteration for dx insert can not stop immediately when
such errors occure.
This patch adds a member 'errcode_t err' to struct dx_insert_ctxt, which
can catch the error and permit ocfs2_dx_dir_insert() returns
OCFS2_EXTENT_ERROR to it's caller to stop the iteration immediately.
Signed-off-by: Coly Li <coly.li@suse.de>
Cc: Mark Fasheh <mfasheh@suse.com>
Cc: Tao Ma <tao.ma@oracle.com>
---
libocfs2/dir_indexed.c | 61 +++++++++++++++++++++++++++++------------------
1 files changed, 38 insertions(+), 23 deletions(-)
diff --git a/libocfs2/dir_indexed.c b/libocfs2/dir_indexed.c
index 5f3db95..08c43b7 100644
--- a/libocfs2/dir_indexed.c
+++ b/libocfs2/dir_indexed.c
@@ -269,6 +269,7 @@ struct dx_insert_ctxt {
uint64_t dir_blkno;
uint64_t dx_root_blkno;
ocfs2_filesys *fs;
+ errcode_t err;
};
@@ -1069,7 +1070,8 @@ static int ocfs2_dx_dir_insert(struct ocfs2_dir_entry *dentry,
char *buf,
void *priv_data)
{
- errcode_t ret = 0;
+ int ret = 0;
+ errcode_t err;
char *dx_buf = NULL;
char *dx_leaf_buf = NULL;
struct ocfs2_dx_root_block *dx_root = NULL;
@@ -1081,17 +1083,17 @@ static int ocfs2_dx_dir_insert(struct ocfs2_dir_entry *dentry,
uint64_t dx_root_blkno = ctxt->dx_root_blkno;
int write_dx_leaf = 0;
- ret = ocfs2_malloc_block(fs->fs_io, &dx_buf);
- if (ret)
- goto out;
+ err = ocfs2_malloc_block(fs->fs_io, &dx_buf);
+ if (err)
+ goto set_err;
- ret = ocfs2_malloc_block(fs->fs_io, &dx_leaf_buf);
- if (ret)
- goto out;
+ err = ocfs2_malloc_block(fs->fs_io, &dx_leaf_buf);
+ if (err)
+ goto set_err;
- ret = ocfs2_read_dx_root(fs, dx_root_blkno, dx_buf);
- if (ret)
- goto out;
+ err = ocfs2_read_dx_root(fs, dx_root_blkno, dx_buf);
+ if (err)
+ goto set_err;
dx_root = (struct ocfs2_dx_root_block *)dx_buf;
memset(&lookup, 0, sizeof(struct ocfs2_dir_lookup_result));
@@ -1104,19 +1106,21 @@ static int ocfs2_dx_dir_insert(struct ocfs2_dir_entry *dentry,
goto insert_into_entries;
} else {
/* root block is full, expand it to an extent */
- ret = ocfs2_expand_inline_dx_root(fs, dx_root);
- if (ret)
- goto out;
+ err = ocfs2_expand_inline_dx_root(fs, dx_root);
+ if (err)
+ goto set_err;
}
}
- ret = ocfs2_find_dir_space_dx(fs, dx_root,
+ err = ocfs2_find_dir_space_dx(fs, dx_root,
dentry->name, dentry->name_len, &lookup);
- if (ret)
- goto out;
- ret = ocfs2_read_dx_leaf(fs, lookup.dl_dx_leaf_blkno, dx_leaf_buf);
- if (ret)
- goto out;
+ if (err)
+ goto set_err;
+
+ err = ocfs2_read_dx_leaf(fs, lookup.dl_dx_leaf_blkno, dx_leaf_buf);
+ if (err)
+ goto set_err;
+
dx_leaf = (struct ocfs2_dx_leaf *)dx_leaf_buf;
entry_list = &dx_leaf->dl_list;
write_dx_leaf = 1;
@@ -1124,12 +1128,18 @@ static int ocfs2_dx_dir_insert(struct ocfs2_dir_entry *dentry,
insert_into_entries:
ocfs2_dx_entry_list_insert(entry_list, &lookup.dl_hinfo, blocknr);
if (write_dx_leaf) {
- ret = ocfs2_write_dx_leaf(fs, dx_leaf->dl_blkno, dx_leaf);
- if (ret)
- goto out;
+ err = ocfs2_write_dx_leaf(fs, dx_leaf->dl_blkno, dx_leaf);
+ if (err)
+ goto set_err;
}
dx_root->dr_num_entries += 1;
- ret = ocfs2_write_dx_root(fs, dx_root_blkno, dx_buf);
+ err = ocfs2_write_dx_root(fs, dx_root_blkno, dx_buf);
+ if (!err)
+ goto out;
+
+set_err:
+ ctxt->err = err;
+ ret = OCFS2_EXTENT_ERROR;
out:
if (dx_leaf_buf)
ocfs2_free(&dx_leaf_buf);
@@ -1256,8 +1266,13 @@ errcode_t ocfs2_dx_dir_build(ocfs2_filesys *fs,
ctxt.dir_blkno = dir;
ctxt.dx_root_blkno = dr_blkno;
ctxt.fs = fs;
+ ctxt.err = 0;
ret = ocfs2_dir_iterate(fs, dir, 0, NULL,
ocfs2_dx_dir_insert, &ctxt);
+ if (ctxt.err)
+ ret = ctxt.err;
+ if (ret)
+ goto out;
/* check quota for dx_leaf */
ret = ocfs2_read_dx_root(fs, dr_blkno, dx_buf);
--
1.7.0.2

View File

@ -0,0 +1,63 @@
From 2dff67994c3d6015b2b989d79a00c2cd10669ed0 Mon Sep 17 00:00:00 2001
From: Coly Li <coly.li@suse.de>
Date: Mon, 26 Apr 2010 22:37:59 +0800
Subject: [PATCH 29/30] dx_dirs: set OCFS2_INDEXED_DIR_FL after indexed tree gets built
In ocfs2_dx_dir_build(), current code set OCFS2_INDEXED_DIR_FL to
di->i_dyn_features before inserting dir entries into the indexed tree.
If there is any error during the insertion, the corresponded dirent will
be lost from the indexed tree. Though this error can be checked and
fixed in fsck.ocfs2, it should be fixed.
This patch modifies to set OCFS2_INDEXED_DIR_FL after
ocfs2_dir_iterate() returns successfully. If ocfs2_dir_iterate() returns
with error, ocfs2_dx_dir_build() will return error and stop to build the
indexed tree for a specific directory. In this case, no dirent will be
losted.
Thanks to Tao Ma to catch this.
Signed-off-by: Coly Li <coly.li@suse.de>
Cc: Mark Fasheh <mfasheh@suse.com>
Cc: Tao Ma <tao.ma@oracle.com>
---
libocfs2/dir_indexed.c | 9 +++++++--
1 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/libocfs2/dir_indexed.c b/libocfs2/dir_indexed.c
index 08c43b7..eb872fd 100644
--- a/libocfs2/dir_indexed.c
+++ b/libocfs2/dir_indexed.c
@@ -1254,7 +1254,6 @@ errcode_t ocfs2_dx_dir_build(ocfs2_filesys *fs,
dx_root->dr_entries.de_count = ocfs2_dx_entries_per_root(fs->fs_blocksize);
di->i_dx_root = dr_blkno;
- di->i_dyn_features |= OCFS2_INDEXED_DIR_FL;
ret = ocfs2_write_dx_root(fs, dr_blkno, dx_buf);
if (ret)
@@ -1274,14 +1273,20 @@ errcode_t ocfs2_dx_dir_build(ocfs2_filesys *fs,
if (ret)
goto out;
- /* check quota for dx_leaf */
ret = ocfs2_read_dx_root(fs, dr_blkno, dx_buf);
if (ret)
goto out;
ret = ocfs2_read_inode(fs, dir, di_buf);
if (ret)
goto out;
+ /* set inode to use indexed-dirs */
+ di->i_dyn_features |= OCFS2_INDEXED_DIR_FL;
+ ret = ocfs2_write_inode(fs, dir, di_buf);
+ if(ret)
+ goto out;
+
+ /* check quota for dx_leaf */
change = ocfs2_clusters_to_bytes(fs,
dx_root->dr_clusters);
uid = di->i_uid;
--
1.7.0.2

View File

@ -0,0 +1,97 @@
From 8cf3a61039b0bda46d8824e50c3989eae83b9a1a Mon Sep 17 00:00:00 2001
From: Coly Li <coly.li@suse.de>
Date: Mon, 26 Apr 2010 22:38:31 +0800
Subject: [PATCH 30/30] dx_dirs: fix ocfs2_swap_dx_entry_list() for big endian
As Tao Ma suggested, current ocfs2_swap_dx_entry_list() is
buggy for big endian hardware, because after dl_list->de_count
swapped, it is referenced in the following loop.
This patch fixes this bug with adding an 'int to_cpu' argument, also
modifies other routines who call ocfs2_swap_dx_entry_list().
Signed-off-by: Coly Li <coly.li@suse.de>
Cc: Mark Fasheh <mfasheh@suse.com>
Cc: Tao Ma <tao.ma@oracle.com>
---
libocfs2/dirblock.c | 23 ++++++++++++++---------
1 files changed, 14 insertions(+), 9 deletions(-)
diff --git a/libocfs2/dirblock.c b/libocfs2/dirblock.c
index c22d843..e128d73 100644
--- a/libocfs2/dirblock.c
+++ b/libocfs2/dirblock.c
@@ -245,29 +245,34 @@ static void ocfs2_swap_dx_entry(struct ocfs2_dx_entry *dx_entry)
dx_entry->dx_dirent_blk = bswap_64(dx_entry->dx_dirent_blk);
}
-static void ocfs2_swap_dx_entry_list(struct ocfs2_dx_entry_list *dl_list)
+/* called for big endian */
+static void ocfs2_swap_dx_entry_list(struct ocfs2_dx_entry_list *dl_list, int to_cpu)
{
int i;
- dl_list->de_count = bswap_16(dl_list->de_count);
- dl_list->de_num_used = bswap_16(dl_list->de_num_used);
+ if (to_cpu)
+ dl_list->de_count = bswap_16(dl_list->de_count);
for (i = 0; i < dl_list->de_count; i++)
ocfs2_swap_dx_entry(&dl_list->de_entries[i]);
+ dl_list->de_num_used = bswap_16(dl_list->de_num_used);
+
+ if (!to_cpu)
+ dl_list->de_count = bswap_16(dl_list->de_count);
}
static void ocfs2_swap_dx_entry_list_to_cpu(struct ocfs2_dx_entry_list *dl_list)
{
if (cpu_is_little_endian)
return;
- ocfs2_swap_dx_entry_list(dl_list);
+ ocfs2_swap_dx_entry_list(dl_list, 1);
}
static void ocfs2_swap_dx_entry_list_from_cpu(struct ocfs2_dx_entry_list *dl_list)
{
if (cpu_is_little_endian)
return;
- ocfs2_swap_dx_entry_list(dl_list);
+ ocfs2_swap_dx_entry_list(dl_list, 0);
}
static void ocfs2_swap_dx_root_to_cpu(ocfs2_filesys *fs,
@@ -384,26 +389,26 @@ out:
return ret;
}
-static void ocfs2_swap_dx_leaf(struct ocfs2_dx_leaf *dx_leaf)
+static void ocfs2_swap_dx_leaf(struct ocfs2_dx_leaf *dx_leaf, int to_cpu)
{
dx_leaf->dl_blkno = bswap_64(dx_leaf->dl_blkno);
dx_leaf->dl_fs_generation = bswap_64(dx_leaf->dl_fs_generation);
- ocfs2_swap_dx_entry_list(&dx_leaf->dl_list);
+ ocfs2_swap_dx_entry_list(&dx_leaf->dl_list, to_cpu);
}
static void ocfs2_swap_dx_leaf_to_cpu(struct ocfs2_dx_leaf *dx_leaf)
{
if (cpu_is_little_endian)
return;
- ocfs2_swap_dx_leaf(dx_leaf);
+ ocfs2_swap_dx_leaf(dx_leaf, 1);
}
static void ocfs2_swap_dx_leaf_from_cpu(struct ocfs2_dx_leaf *dx_leaf)
{
if (cpu_is_little_endian)
return;
- ocfs2_swap_dx_leaf(dx_leaf);
+ ocfs2_swap_dx_leaf(dx_leaf, 0);
}
errcode_t ocfs2_read_dx_leaf(ocfs2_filesys *fs, uint64_t block,
--
1.7.0.2

View File

@ -0,0 +1,87 @@
From 76e095ae3d132828bbb70bad68c428101d3652a9 Mon Sep 17 00:00:00 2001
From: Coly Li <coly.li@suse.de>
Date: Sun, 11 Apr 2010 00:03:33 +0800
Subject: [PATCH 15/15] dx_dirs v11: enable metaecc and indexed-dirs support as default features
metaecc feature enables ECC checking for meta data, which helps the file
system consistency. indexed-dirs feature enables indexed tree for
directories, which improves lookup performance for large scale
directories.
This patch enables metaecc and indexed-dirs support as default features.
Signed-off-by: Coly Li <coly.li@suse.de>
Cc: Mark Fasheh <mfasheh@suse.com>
---
libocfs2/feature_string.c | 18 ++++++++++++++----
mkfs.ocfs2/mkfs.ocfs2.8.in | 2 +-
2 files changed, 15 insertions(+), 5 deletions(-)
diff --git a/libocfs2/feature_string.c b/libocfs2/feature_string.c
index 0974fb6..b2413bf 100644
--- a/libocfs2/feature_string.c
+++ b/libocfs2/feature_string.c
@@ -76,7 +76,9 @@ static ocfs2_fs_options feature_level_defaults[] = {
{OCFS2_FEATURE_COMPAT_BACKUP_SB | OCFS2_FEATURE_COMPAT_JBD2_SB,
OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC |
OCFS2_FEATURE_INCOMPAT_INLINE_DATA |
- OCFS2_FEATURE_INCOMPAT_XATTR,
+ OCFS2_FEATURE_INCOMPAT_XATTR |
+ OCFS2_FEATURE_INCOMPAT_META_ECC |
+ OCFS2_FEATURE_INCOMPAT_INDEXED_DIRS,
OCFS2_FEATURE_RO_COMPAT_UNWRITTEN}, /* OCFS2_FEATURE_LEVEL_DEFAULT */
{OCFS2_FEATURE_COMPAT_BACKUP_SB | OCFS2_FEATURE_COMPAT_JBD2_SB,
@@ -100,25 +102,33 @@ static ocfs2_fs_options mkfstypes_features_defaults[] = {
{OCFS2_FEATURE_COMPAT_BACKUP_SB | OCFS2_FEATURE_COMPAT_JBD2_SB,
OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC |
OCFS2_FEATURE_INCOMPAT_INLINE_DATA |
- OCFS2_FEATURE_INCOMPAT_XATTR,
+ OCFS2_FEATURE_INCOMPAT_XATTR |
+ OCFS2_FEATURE_INCOMPAT_META_ECC |
+ OCFS2_FEATURE_INCOMPAT_INDEXED_DIRS,
OCFS2_FEATURE_RO_COMPAT_UNWRITTEN}, /* OCFS2_MKFSTYPE_DEFAULT */
{OCFS2_FEATURE_COMPAT_BACKUP_SB | OCFS2_FEATURE_COMPAT_JBD2_SB,
OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC |
OCFS2_FEATURE_INCOMPAT_INLINE_DATA |
- OCFS2_FEATURE_INCOMPAT_XATTR,
+ OCFS2_FEATURE_INCOMPAT_XATTR |
+ OCFS2_FEATURE_INCOMPAT_META_ECC |
+ OCFS2_FEATURE_INCOMPAT_INDEXED_DIRS,
OCFS2_FEATURE_RO_COMPAT_UNWRITTEN}, /* OCFS2_MKFSTYPE_DATAFILES */
{OCFS2_FEATURE_COMPAT_BACKUP_SB | OCFS2_FEATURE_COMPAT_JBD2_SB,
OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC |
OCFS2_FEATURE_INCOMPAT_INLINE_DATA |
- OCFS2_FEATURE_INCOMPAT_XATTR,
+ OCFS2_FEATURE_INCOMPAT_XATTR |
+ OCFS2_FEATURE_INCOMPAT_META_ECC |
+ OCFS2_FEATURE_INCOMPAT_INDEXED_DIRS,
OCFS2_FEATURE_RO_COMPAT_UNWRITTEN}, /* OCFS2_MKFSTYPE_MAIL */
{OCFS2_FEATURE_COMPAT_BACKUP_SB | OCFS2_FEATURE_COMPAT_JBD2_SB,
OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC |
OCFS2_FEATURE_INCOMPAT_INLINE_DATA |
OCFS2_FEATURE_INCOMPAT_XATTR |
+ OCFS2_FEATURE_INCOMPAT_META_ECC |
+ OCFS2_FEATURE_INCOMPAT_INDEXED_DIRS |
OCFS2_FEATURE_INCOMPAT_REFCOUNT_TREE,
OCFS2_FEATURE_RO_COMPAT_UNWRITTEN}, /* OCFS2_MKFSTYPE_VMSTORE */
};
diff --git a/mkfs.ocfs2/mkfs.ocfs2.8.in b/mkfs.ocfs2/mkfs.ocfs2.8.in
index a148133..2fd7a70 100644
--- a/mkfs.ocfs2/mkfs.ocfs2.8.in
+++ b/mkfs.ocfs2/mkfs.ocfs2.8.in
@@ -191,7 +191,7 @@ Chooses fewer features but ensures that the file system can be mounted from olde
.RS 1.2i
.TP
\fBdefault\fR
-The default feature set tries to strike a balance between providing new features and maintaining compatibility with relatively recent versions of \fIOCFS2\fR. It currently enables \fBsparse\fR, \fBunwritten\fR \fBinline-data\fR and \fBxattr\fR. It also enables \fBrefcount\fR for the \fIvmstore\fR volumes.
+The default feature set tries to strike a balance between providing new features and maintaining compatibility with relatively recent versions of \fIOCFS2\fR. It currently enables \fBsparse\fR, \fBunwritten\fR, \fBinline-data\fR, \fRxattr\fR, \fRmetaecc\fR, and \fRindexed-dirs\fR. It also enables \fBrefcount\fR for the \fIvmstore\fR volumes.
.RE
.RS 1.2i
.TP
--
1.7.0.2

View File

@ -0,0 +1,39 @@
Index: ocfs2-tools/libo2cb/o2cb_err.et
===================================================================
--- ocfs2-tools.orig/libo2cb/o2cb_err.et
+++ ocfs2-tools/libo2cb/o2cb_err.et
@@ -33,6 +33,12 @@ ec O2CB_ET_IO,
ec O2CB_ET_SERVICE_UNAVAILABLE,
"Unable to access cluster service"
+ec O2CB_ET_SERVICE_HANDSHAKE_UNAVAILABLE,
+ "Unable to access cluster serivce due to bad handshake"
+
+ec O2CB_ET_SERVICE_DEV_UNAVAILABLE,
+ "Unable to access cluster service device"
+
ec O2CB_ET_INTERNAL_FAILURE,
"Internal logic failure"
Index: ocfs2-tools/libo2cb/o2cb_abi.c
===================================================================
--- ocfs2-tools.orig/libo2cb/o2cb_abi.c
+++ ocfs2-tools/libo2cb/o2cb_abi.c
@@ -2095,7 +2095,7 @@ static errcode_t o2cb_control_handshake(
if (ret != 0)
err = O2CB_ET_IO;
else if (!found)
- err = O2CB_ET_SERVICE_UNAVAILABLE; /* no match */
+ err = O2CB_ET_SERVICE_HANDSHAKE_UNAVAILABLE; /* no match */
break;
}
@@ -2152,7 +2152,7 @@ errcode_t o2cb_control_open(unsigned int
case ENOTDIR:
case ENOENT:
case EISDIR:
- err = O2CB_ET_SERVICE_UNAVAILABLE;
+ err = O2CB_ET_SERVICE_DEV_UNAVAILABLE;
break;
case EACCES:

12
bug-543119-o2dlm.patch Normal file
View File

@ -0,0 +1,12 @@
diff -rup ocfs2-tools.orig//libo2dlm/o2dlm.c ocfs2-tools/libo2dlm/o2dlm.c
--- ocfs2-tools.orig//libo2dlm/o2dlm.c 2008-10-27 01:10:50.000000000 +0800
+++ ocfs2-tools/libo2dlm/o2dlm.c 2009-11-03 16:49:38.000000000 +0800
@@ -713,7 +713,7 @@ static errcode_t load_fsdlm(struct o2dlm
goto out;
}
- ctxt->ct_lib_handle = dlopen("libdlm_lt.so",
+ ctxt->ct_lib_handle = dlopen("libdlm_lt.so.3",
RTLD_NOW | RTLD_LOCAL);
if (!ctxt->ct_lib_handle)
goto out;

View File

@ -0,0 +1,47 @@
This is a simple patch which fix the issue that tunefs.ocfs2 online
resize can't handle symbolic link of a device file. For example, in
the LVM using scenario, '/dev/vg1/lv1' and '/dev/mapper/vg1-lv1' are
the same device, '/dev/vg1/lv1' is just a symbolic link to
'/dev/mapper/vg1-lv1'. But if we try to do online resize like
'tunefs.ocfs2 -S /dev/vg1/lv1', it fails.
Signed-off-by: Jiaju Zhang <jjzhang@suse.de>
---
ocfs2_controld/mount.c | 20 +++++++++++++++++---
1 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/ocfs2_controld/mount.c b/ocfs2_controld/mount.c
--- a/ocfs2_controld/mount.c
+++ b/ocfs2_controld/mount.c
@@ -260,13 +260,27 @@ static void add_service(struct mountgroup *mg, const char *device,
const char *service, int ci, int fd)
{
struct service *ms;
+ struct stat st1, st2;
- log_debug("Adding service %s to device %s uuid %s",
+ log_debug("Adding service \"%s\" to device \"%s\" uuid \"%s\"",
service, device, mg->mg_uuid);
- if (strcmp(mg->mg_device, device)) {
+ if (stat(mg->mg_device, &st1)) {
+ fill_error(mg, errno, "Failed to stat device \"%s\": %s",
+ mg->mg_device, strerror(errno));
+ return;
+ }
+
+ if (stat(device, &st2)) {
+ fill_error(mg, errno, "Failed to stat device \"%s\": %s",
+ device, strerror(errno));
+ return;
+ }
+
+ if (st1.st_rdev != st2.st_rdev) {
fill_error(mg, EINVAL,
- "Trying to mount fs %s on device %s, but it is already mounted from device %s",
+ "Trying to mount fs \"%s\" on device \"%s\", "
+ "but it is already mounted from device \"%s\"",
mg->mg_uuid, device, mg->mg_device);
return;
}

View File

@ -1,30 +0,0 @@
diff --git a/include/ocfs2-kernel/ocfs2_fs.h b/include/ocfs2-kernel/ocfs2_fs.h
index d27b098..b29abdc 100644
--- a/include/ocfs2-kernel/ocfs2_fs.h
+++ b/include/ocfs2-kernel/ocfs2_fs.h
@@ -354,8 +354,8 @@ static struct ocfs2_system_inode_info ocfs2_system_inodes[NUM_SYSTEM_INODES] = {
[JOURNAL_SYSTEM_INODE] = { "journal:%04d", OCFS2_JOURNAL_FL, S_IFREG | 0644 },
[LOCAL_ALLOC_SYSTEM_INODE] = { "local_alloc:%04d", OCFS2_BITMAP_FL | OCFS2_LOCAL_ALLOC_FL, S_IFREG | 0644 },
[TRUNCATE_LOG_SYSTEM_INODE] = { "truncate_log:%04d", OCFS2_DEALLOC_FL, S_IFREG | 0644 },
- [LOCAL_USER_QUOTA_SYSTEM_INODE] = { "aquota%04d.user", OCFS2_QUOTA_FL, S_IFREG | 0644 },
- [LOCAL_GROUP_QUOTA_SYSTEM_INODE] = { "aquota%04d.group", OCFS2_QUOTA_FL, S_IFREG | 0644 },
+ [LOCAL_USER_QUOTA_SYSTEM_INODE] = { "aquota.user:%04d", OCFS2_QUOTA_FL, S_IFREG | 0644 },
+ [LOCAL_GROUP_QUOTA_SYSTEM_INODE] = { "aquota.group:%04d", OCFS2_QUOTA_FL, S_IFREG | 0644 },
};
/* Parameter passed from mount.ocfs2 to module */
diff --git a/mkfs.ocfs2/mkfs.c b/mkfs.ocfs2/mkfs.c
index 9fe2ac2..441df68 100644
--- a/mkfs.ocfs2/mkfs.c
+++ b/mkfs.ocfs2/mkfs.c
@@ -104,8 +104,8 @@ static SystemFileInfo system_files[] = {
{ "journal:%04d", SFI_JOURNAL, 0, S_IFREG | 0644 },
{ "local_alloc:%04d", SFI_LOCAL_ALLOC, 0, S_IFREG | 0644 },
{ "truncate_log:%04d", SFI_TRUNCATE_LOG, 0, S_IFREG | 0644 },
- { "aquota%04d.user", SFI_QUOTA, 0, S_IFREG | 0644 },
- { "aquota%04d.group", SFI_QUOTA, 0, S_IFREG | 0644 },
+ { "aquota.user:%04d", SFI_QUOTA, 0, S_IFREG | 0644 },
+ { "aquota.group:%04d", SFI_QUOTA, 0, S_IFREG | 0644 },
};
struct fs_type_translation {

104
debug-ocfs2_hb_ctl.patch Normal file
View File

@ -0,0 +1,104 @@
Index: ocfs2-tools/ocfs2_hb_ctl/ocfs2_hb_ctl.c
===================================================================
--- ocfs2-tools.orig/ocfs2_hb_ctl/ocfs2_hb_ctl.c
+++ ocfs2-tools/ocfs2_hb_ctl/ocfs2_hb_ctl.c
@@ -39,6 +39,7 @@
#include <string.h>
#include <sys/stat.h>
#include <signal.h>
+#include <syslog.h>
#include "ocfs2/ocfs2.h"
@@ -137,6 +138,7 @@ static errcode_t get_desc(const char *de
if (!region_desc->r_name || !region_desc->r_device_name)
err = OCFS2_ET_NO_MEMORY;
} else {
+ syslog(LOG_INFO, "filled heartbeat desc, err: %d\n", (int)err);
region_desc->r_name = NULL;
region_desc->r_device_name = NULL;
goto out_close;
@@ -157,6 +159,7 @@ static errcode_t get_desc(const char *de
err = OCFS2_ET_NO_MEMORY;
}
} else {
+ syslog(LOG_INFO, "filled cluster desc, err: %d\n", (int)err);
cluster_desc->c_stack = NULL;
cluster_desc->c_cluster = NULL;
}
@@ -202,9 +205,9 @@ static errcode_t compare_dev(const char
/* Any problem with getting the descriptor is NOT FOUND */
err = OCFS2_ET_FILE_NOT_FOUND;
- if (get_desc(device))
+ if (get_desc(device)) {
goto out;
-
+ }
if (!strcmp(region_desc->r_name, hbo->uuid_str)) {
hbo->dev_str = device;
err = 0;
@@ -381,12 +384,19 @@ static errcode_t stop_heartbeat(struct h
{
errcode_t err = 0;
- if (!hbo->dev_str)
+ if (!hbo->dev_str) {
err = lookup_dev(hbo);
+ if (err)
+ syslog(LOG_INFO, "looked up device, ret: %d\n",
+ (int)err);
+ }
if (!err) {
region_desc->r_persist = 1; /* hb_ctl is for reals */
region_desc->r_service = hbo->service;
err = o2cb_group_leave(cluster_desc, region_desc);
+ if (err)
+ syslog(LOG_INFO, "left group - err: %d\n",
+ (int)err);
}
return err;
@@ -536,14 +546,42 @@ static void print_usage(int err)
fprintf(output, " %s -h\n", progname);
}
+static int
+hack_enable_coredumps(void)
+{
+ struct rlimit rlim;
+
+ if (getrlimit(RLIMIT_CORE, &rlim) < 0) {
+ return -1;
+ }
+
+ rlim.rlim_max = RLIM_INFINITY;
+ setrlimit(RLIMIT_CORE, &rlim);
+ (void)chdir("/var/lib/openais");
+ return 0;
+}
+
+
int main(int argc, char **argv)
{
errcode_t err = 0;
int ret = 0;
+ int i;
struct hb_ctl_options hbo = {
.action = HB_ACTION_UNKNOWN,
};
char hbuuid[33];
+ char tmp[1024];
+
+ openlog("ocfs2_hb_ctl", LOG_CONS|LOG_NDELAY|LOG_PID, LOG_KERN);
+ sprintf(tmp, "ocfs2_hb_ctl");
+ for (i = 0; i < argc; i++) {
+ strncat(tmp, " ", sizeof(tmp)-1);
+ strncat(tmp, argv[i], sizeof(tmp)-1);
+ }
+ syslog(LOG_INFO, "%s\n", tmp);
+
+ hack_enable_coredumps();
setbuf(stdout, NULL);
setbuf(stderr, NULL);

187
extra-debug.patch Normal file
View File

@ -0,0 +1,187 @@
---
ocfs2_controld/ckpt.c | 2 -
ocfs2_controld/main.c | 53 ++++++++++++++++++++++++++++++++++------
ocfs2_controld/mount.c | 2 +
ocfs2_controld/ocfs2_controld.h | 1
ocfs2_controld/pacemaker.c | 2 -
5 files changed, 51 insertions(+), 9 deletions(-)
Index: ocfs2_controld/ckpt.c
===================================================================
--- a/ocfs2_controld/ckpt.c.orig
+++ b/ocfs2_controld/ckpt.c
@@ -381,7 +381,7 @@ static int call_section_read(struct ckpt
/* -ENOENT is a clean error for the caller to handle */
if (rc == -ENOENT) {
- log_debug("Checkpoint \"%.*s\" does not have a "
+ log_error("Checkpoint \"%.*s\" does not have a "
"section named \"%s\"",
handle->ch_name.length,
handle->ch_name.value, name);
Index: ocfs2_controld/main.c
===================================================================
--- a/ocfs2_controld/main.c.orig
+++ b/ocfs2_controld/main.c
@@ -73,7 +73,7 @@ static int time_to_die = 0;
static int sigpipe_write_fd;
char *prog_name;
-int daemon_debug_opt;
+int daemon_debug_opt = 0;
char daemon_debug_buf[1024];
char dump_buf[DUMP_SIZE];
int dump_point;
@@ -994,8 +994,7 @@ static void lockfile(void)
fd = open(LOCKFILE_NAME, O_CREAT|O_WRONLY,
S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
if (fd < 0) {
- fprintf(stderr, "cannot open/create lock file %s\n",
- LOCKFILE_NAME);
+ log_error("cannot open/create lock file %s", LOCKFILE_NAME);
exit(EXIT_FAILURE);
}
@@ -1006,13 +1005,13 @@ static void lockfile(void)
error = fcntl(fd, F_SETLK, &lock);
if (error) {
- fprintf(stderr, "ocfs2_controld is already running\n");
+ log_error("ocfs2_controld is already running");
exit(EXIT_FAILURE);
}
error = ftruncate(fd, 0);
if (error) {
- fprintf(stderr, "cannot clear lock file %s\n", LOCKFILE_NAME);
+ log_error("cannot clear lock file %s", LOCKFILE_NAME);
exit(EXIT_FAILURE);
}
@@ -1020,7 +1019,7 @@ static void lockfile(void)
error = write(fd, buf, strlen(buf));
if (error <= 0) {
- fprintf(stderr, "cannot write lock file %s\n", LOCKFILE_NAME);
+ log_error("cannot write lock file %s", LOCKFILE_NAME);
exit(EXIT_FAILURE);
}
}
@@ -1030,13 +1029,13 @@ static void daemonize(void)
int fd;
pid_t pid = fork();
if (pid < 0) {
+ log_error("main: cannot fork");
perror("main: cannot fork");
exit(EXIT_FAILURE);
}
if (pid)
exit(EXIT_SUCCESS);
setsid();
- chdir("/");
umask(0);
close(0);
close(1);
@@ -1107,6 +1106,7 @@ static void decode_arguments(int argc, c
break;
default:
+ log_error("unknown option: %c\n", optchar);
fprintf(stderr, "unknown option: %c\n", optchar);
exit(EXIT_FAILURE);
break;
@@ -1144,12 +1144,53 @@ static void set_scheduler(void)
}
}
+#include <sys/time.h>
+#include <sys/resource.h>
+
+static int
+hack_enable_coredumps(void)
+{
+ int rc;
+ struct rlimit rlim;
+ int doenable = 1;
+
+ if ((rc = getrlimit(RLIMIT_CORE, &rlim)) < 0) {
+ int errsave = errno;
+ log_error("Cannot get current core limit value. %d", errsave);
+ errno = errsave;
+ return rc;
+ }
+ if (rlim.rlim_max == 0 && geteuid() == 0) {
+ rlim.rlim_max = RLIM_INFINITY;
+ }
+
+ rlim.rlim_cur = (doenable ? rlim.rlim_max : 0);
+
+ if (doenable && rlim.rlim_max == 0) {
+ log_error("Not possible to enable core dumps (rlim_max is 0)");
+ }
+
+ if ((rc = setrlimit(RLIMIT_CORE, &rlim)) < 0) {
+ int errsave = errno;
+ log_error("Unable to enable core dumps: %d", errsave);
+ errno = errsave;
+ return rc;
+ }
+ chdir("/var/lib/openais");
+ log_debug("Core dumps enabled: /var/lib/openais");
+ return 0;
+}
+
int main(int argc, char **argv)
{
errcode_t err;
prog_name = argv[0];
const char *stack = NULL;
+ decode_arguments(argc, argv);
+
+ hack_enable_coredumps();
+
init_mounts();
initialize_o2cb_error_table();
@@ -1165,13 +1206,11 @@ int main(int argc, char **argv)
return 1;
}
if (strcmp(stack, stackname)) {
- fprintf(stderr, "%s: This daemon supports the \"%s\" stack, but the \"%s\" stack is in use\n",
- prog_name, stackname, stack);
+ log_error("%s: This daemon supports the \"%s\" stack, but the \"%s\" stack is in use",
+ prog_name, stackname, stack);
return 1;
}
- decode_arguments(argc, argv);
-
if (!daemon_debug_opt)
daemonize();
Index: ocfs2_controld/mount.c
===================================================================
--- a/ocfs2_controld/mount.c.orig
+++ b/ocfs2_controld/mount.c
@@ -176,6 +176,8 @@ static void notify_mount_client(struct m
else
mg->mg_mount_notified = 1;
+ log_debug("Notified client: %d", mg->mg_mount_notified);
+
/*
* XXX If we failed to notify the client, what can we do? I'm
* guessing that our main loop will get POLLHUP and we'll clean
Index: ocfs2_controld/ocfs2_controld.h
===================================================================
--- a/ocfs2_controld/ocfs2_controld.h.orig
+++ b/ocfs2_controld/ocfs2_controld.h
@@ -60,6 +60,7 @@ do { \
#define log_error(fmt, args...) \
do { \
log_debug(fmt, ##args); \
+ fprintf(stderr, fmt "\n", ##args); \
syslog(LOG_ERR, fmt, ##args); \
} while (0)

28
force-debug.patch Normal file
View File

@ -0,0 +1,28 @@
---
ocfs2_controld/ocfs2_controld.h | 7 +++++++
1 file changed, 7 insertions(+)
Index: ocfs2_controld/ocfs2_controld.h
===================================================================
--- a/ocfs2_controld/ocfs2_controld.h.orig 2008-10-26 18:10:50.000000000 +0100
+++ b/ocfs2_controld/ocfs2_controld.h 2009-03-10 22:22:52.719197000 +0100
@@ -44,12 +44,19 @@ extern void daemon_dump_save(void);
#define log_debug(fmt, args...) \
do { \
+ syslog(LOG_DEBUG, fmt, ##args); \
snprintf(daemon_debug_buf, 1023, "%ld %s@%d: " fmt "\n", \
time(NULL), __FUNCTION__, __LINE__, ##args); \
if (daemon_debug_opt) fprintf(stderr, "%s", daemon_debug_buf); \
daemon_dump_save(); \
} while (0)
+#define log_info(fmt, args...) \
+do { \
+ log_debug(fmt, ##args); \
+ syslog(LOG_INFO, fmt, ##args); \
+} while (0)
+
#define log_error(fmt, args...) \
do { \
log_debug(fmt, ##args); \

View File

@ -168,19 +168,18 @@ bringup_daemon()
kill_daemon()
{
status_daemon; rc=$?
if [ $rc != $OCF_SUCCESS ]; then
return $rc
if [ $rc == $OCF_NOT_RUNNING ]; then
return 0
fi
ocf_log info "Stopping `basename "$DAEMON"`"
killproc "$DAEMON"
while [ $rc = $OCF_NOT_RUNNING ]; do
while [ $rc != $OCF_NOT_RUNNING ]; do
sleep 1
status_daemon; rc=$?
done
return $OCF_SUCCESS
return 0
}
#

View File

@ -1,33 +1,6 @@
--- ocfs2-tools/ocfs2_controld/main.c
+++ ocfs2-tools/ocfs2_controld/main.c
@@ -1027,6 +1027,7 @@
static void daemonize(void)
{
+ int fd;
pid_t pid = fork();
if (pid < 0) {
perror("main: cannot fork");
@@ -1040,6 +1041,18 @@
close(0);
close(1);
close(2);
+ fd = open("/dev/null", O_RDWR);
+ if (fd >= 0) {
+ /* dup2 to 0 / 1 / 2 (stdin / stdout / stderr) */
+ dup2(fd, STDIN_FILENO); /* 0 */
+ dup2(fd, STDOUT_FILENO); /* 1 */
+ dup2(fd, STDERR_FILENO); /* 2 */
+
+ /* Should be 0, but just in case it isn't... */
+ if (fd > 2) {
+ close(fd);
+ }
+ }
openlog("ocfs2_controld", LOG_PID, LOG_DAEMON);
lockfile();
--- ocfs2-tools/vendor/common/o2cb.init.sh
Index: ocfs2-tools/vendor/common/o2cb.init.sh
===================================================================
--- ocfs2-tools.orig/vendor/common/o2cb.init.sh
+++ ocfs2-tools/vendor/common/o2cb.init.sh
@@ -8,7 +8,8 @@
# Provides: o2cb
@ -39,7 +12,7 @@
# Default-Start: 2 3 5
# Default-Stop:
# Short-Description: Load O2CB cluster services at system boot.
@@ -653,7 +654,7 @@
@@ -653,7 +654,7 @@ status_filesystem()
status_daemon()
{
@ -48,16 +21,7 @@
echo -n "Checking for control daemon: "
if [ -n "$(pidofproc "$DAEMON")" ]
then
@@ -667,7 +668,7 @@
bringup_daemon()
{
- DAEMON="/sbin/ocfs2_controld.${O2CB_STACK}"
+ DAEMON="/usr/sbin/ocfs2_controld.${O2CB_STACK}"
echo -n "Starting $(basename "$DAEMON"): "
start_daemon "$DAEMON"
[ $? != 0 ] && return 1
@@ -682,6 +683,7 @@
@@ -682,6 +683,7 @@ bringup_daemon()
fi
sleep 1
done
@ -65,7 +29,7 @@
return 0
}
@@ -689,7 +691,7 @@
@@ -689,7 +691,7 @@ bringup_daemon()
kill_daemon()
{
SIGNAL="$1"
@ -74,7 +38,9 @@
status_daemon >/dev/null 2>&1 || return 2
--- ocfs2-tools/vendor/common/ocfs2.init
Index: ocfs2-tools/vendor/common/ocfs2.init
===================================================================
--- ocfs2-tools.orig/vendor/common/ocfs2.init
+++ ocfs2-tools/vendor/common/ocfs2.init
@@ -8,9 +8,9 @@
### BEGIN INIT INFO

View File

@ -1,21 +0,0 @@
Index: mount.ocfs2/mount.ocfs2.c
===================================================================
--- mount.ocfs2/mount.ocfs2.c.orig
+++ mount.ocfs2/mount.ocfs2.c
@@ -261,7 +261,7 @@ int main(int argc, char **argv)
char *extra = NULL;
int dev_ro = 0;
char *hbstr = NULL;
- char stackstr[strlen(OCFS2_CLUSTER_STACK_ARG) + OCFS2_STACK_LABEL_LEN + 1] = "";
+ char stackstr[strlen(OCFS2_CLUSTER_STACK_ARG) + OCFS2_STACK_LABEL_LEN + 1];
ocfs2_filesys *fs = NULL;
struct o2cb_cluster_desc cluster;
struct o2cb_region_desc desc;
@@ -269,6 +269,7 @@ int main(int argc, char **argv)
int hb_started = 0;
struct stat statbuf;
+ stackstr[0] = '\0';
initialize_ocfs_error_table();
initialize_o2dl_error_table();
initialize_o2cb_error_table();

View File

@ -1,7 +1,8 @@
diff -ru ocfs2-tools/o2cb_ctl/Makefile ocfs2-tools.fix/o2cb_ctl/Makefile
--- ocfs2-tools/o2cb_ctl/Makefile 2007-11-13 04:19:54.000000000 -0500
+++ ocfs2-tools.fix/o2cb_ctl/Makefile 2008-02-19 15:00:40.000000000 -0500
@@ -49,6 +49,6 @@
Index: ocfs2-tools/o2cb_ctl/Makefile
===================================================================
--- ocfs2-tools.orig/o2cb_ctl/Makefile
+++ ocfs2-tools/o2cb_ctl/Makefile
@@ -40,6 +40,6 @@ o2cb_config_CPPFLAGS = $(GLIB_CFLAGS) -D
o2cb_ctl_CPPFLAGS = $(GLIB_CFLAGS) -DG_DISABLE_DEPRECATED
o2cb_ctl: $(O2CB_CTL_OBJS) $(LIBOCFS2_DEPS) $(LIBO2CB_DEPS)

View File

@ -1,795 +0,0 @@
>From 4220f907aba2afa2c045f26f0d9afe465aea6863 Mon Sep 17 00:00:00 2001
From: Jan Kara <jack@suse.cz>
Date: Tue, 14 Oct 2008 15:44:31 +0200
Subject: [PATCH] Implement quota support to mkfs and add a few auxiliary functions for quotas
into libocfs2.
Signed-off-by: Jan Kara <jack@suse.cz>
---
Preamble.make | 3 +-
include/ocfs2-kernel/ocfs2_fs.h | 114 +++++++++++++++++-
include/ocfs2/ocfs2.h | 25 ++++
libocfs2/Makefile | 1 +
libocfs2/feature_string.c | 22 +++-
libocfs2/quota.c | 261 +++++++++++++++++++++++++++++++++++++++
mkfs.ocfs2/mkfs.c | 140 +++++++++++++++++++++-
mkfs.ocfs2/mkfs.h | 1 +
o2image/Makefile | 2 +-
9 files changed, 563 insertions(+), 6 deletions(-)
create mode 100644 libocfs2/quota.c
diff --git a/include/ocfs2-kernel/ocfs2_fs.h b/include/ocfs2-kernel/ocfs2_fs.h
index e454099..d27b098 100644
--- a/include/ocfs2-kernel/ocfs2_fs.h
+++ b/include/ocfs2-kernel/ocfs2_fs.h
@@ -92,7 +92,9 @@
| OCFS2_FEATURE_INCOMPAT_INLINE_DATA \
| OCFS2_FEATURE_INCOMPAT_EXTENDED_SLOT_MAP \
| OCFS2_FEATURE_INCOMPAT_USERSPACE_STACK)
-#define OCFS2_FEATURE_RO_COMPAT_SUPP OCFS2_FEATURE_RO_COMPAT_UNWRITTEN
+#define OCFS2_FEATURE_RO_COMPAT_SUPP (OCFS2_FEATURE_RO_COMPAT_UNWRITTEN \
+ | OCFS2_FEATURE_RO_COMPAT_USRQUOTA \
+ | OCFS2_FEATURE_RO_COMPAT_GRPQUOTA)
/*
* Heartbeat-only devices are missing journals and other files. The
@@ -159,6 +161,12 @@
*/
#define OCFS2_FEATURE_RO_COMPAT_UNWRITTEN 0x0001
+/*
+ * Maintain quota information for this filesystem
+ */
+#define OCFS2_FEATURE_RO_COMPAT_USRQUOTA 0x0002
+#define OCFS2_FEATURE_RO_COMPAT_GRPQUOTA 0x0004
+
/* The byte offset of the first backup block will be 1G.
* The following will be 4G, 16G, 64G, 256G and 1T.
*/
@@ -188,6 +196,7 @@
#define OCFS2_HEARTBEAT_FL (0x00000200) /* Heartbeat area */
#define OCFS2_CHAIN_FL (0x00000400) /* Chain allocator */
#define OCFS2_DEALLOC_FL (0x00000800) /* Truncate log */
+#define OCFS2_QUOTA_FL (0x00001000) /* Quota file */
/*
* Flags on ocfs2_dinode.i_dyn_features
@@ -311,6 +320,8 @@ enum {
#define OCFS2_FIRST_ONLINE_SYSTEM_INODE SLOT_MAP_SYSTEM_INODE
HEARTBEAT_SYSTEM_INODE,
GLOBAL_BITMAP_SYSTEM_INODE,
+ USER_QUOTA_SYSTEM_INODE,
+ GROUP_QUOTA_SYSTEM_INODE,
#define OCFS2_LAST_GLOBAL_SYSTEM_INODE GLOBAL_BITMAP_SYSTEM_INODE
ORPHAN_DIR_SYSTEM_INODE,
EXTENT_ALLOC_SYSTEM_INODE,
@@ -318,6 +329,8 @@ enum {
JOURNAL_SYSTEM_INODE,
LOCAL_ALLOC_SYSTEM_INODE,
TRUNCATE_LOG_SYSTEM_INODE,
+ LOCAL_USER_QUOTA_SYSTEM_INODE,
+ LOCAL_GROUP_QUOTA_SYSTEM_INODE,
NUM_SYSTEM_INODES
};
@@ -331,6 +344,8 @@ static struct ocfs2_system_inode_info ocfs2_system_inodes[NUM_SYSTEM_INODES] = {
[SLOT_MAP_SYSTEM_INODE] = { "slot_map", 0, S_IFREG | 0644 },
[HEARTBEAT_SYSTEM_INODE] = { "heartbeat", OCFS2_HEARTBEAT_FL, S_IFREG | 0644 },
[GLOBAL_BITMAP_SYSTEM_INODE] = { "global_bitmap", 0, S_IFREG | 0644 },
+ [USER_QUOTA_SYSTEM_INODE] = { "aquota.user", OCFS2_QUOTA_FL, S_IFREG | 0644 },
+ [GROUP_QUOTA_SYSTEM_INODE] = { "aquota.group", OCFS2_QUOTA_FL, S_IFREG | 0644 },
/* Slot-specific system inodes (one copy per slot) */
[ORPHAN_DIR_SYSTEM_INODE] = { "orphan_dir:%04d", 0, S_IFDIR | 0755 },
@@ -338,7 +353,9 @@ static struct ocfs2_system_inode_info ocfs2_system_inodes[NUM_SYSTEM_INODES] = {
[INODE_ALLOC_SYSTEM_INODE] = { "inode_alloc:%04d", OCFS2_BITMAP_FL | OCFS2_CHAIN_FL, S_IFREG | 0644 },
[JOURNAL_SYSTEM_INODE] = { "journal:%04d", OCFS2_JOURNAL_FL, S_IFREG | 0644 },
[LOCAL_ALLOC_SYSTEM_INODE] = { "local_alloc:%04d", OCFS2_BITMAP_FL | OCFS2_LOCAL_ALLOC_FL, S_IFREG | 0644 },
- [TRUNCATE_LOG_SYSTEM_INODE] = { "truncate_log:%04d", OCFS2_DEALLOC_FL, S_IFREG | 0644 }
+ [TRUNCATE_LOG_SYSTEM_INODE] = { "truncate_log:%04d", OCFS2_DEALLOC_FL, S_IFREG | 0644 },
+ [LOCAL_USER_QUOTA_SYSTEM_INODE] = { "aquota%04d.user", OCFS2_QUOTA_FL, S_IFREG | 0644 },
+ [LOCAL_GROUP_QUOTA_SYSTEM_INODE] = { "aquota%04d.group", OCFS2_QUOTA_FL, S_IFREG | 0644 },
};
/* Parameter passed from mount.ocfs2 to module */
@@ -713,6 +730,99 @@ struct ocfs2_group_desc
/*40*/ __u8 bg_bitmap[0];
};
+/* Magic numbers and known versions for local quota files */
+#define OCFS2_LOCAL_QMAGICS {\
+ 0x0cf524c0, /* USRQUOTA */ \
+ 0x0cf524c1 /* GRPQUOTA */ \
+}
+
+#define OCFS2_LOCAL_QVERSIONS {\
+ 0, \
+ 0, \
+}
+
+/* Magic numbers and known versions for global quota files */
+#define OCFS2_GLOBAL_QMAGICS {\
+ 0x0cf52470, /* USRQUOTA */ \
+ 0x0cf52471 /* GRPQUOTA */ \
+}
+
+#define OCFS2_GLOBAL_QVERSIONS {\
+ 0, \
+ 0, \
+}
+
+/* How many bytes to we reserve in each quota file block for our internal
+ * purposes? E.g. checksums... */
+#define OCFS2_QBLK_RESERVED_SPACE 8
+
+/* Generic header of all quota files */
+struct ocfs2_disk_dqheader {
+ __le32 dqh_magic; /* Magic number identifying file */
+ __le32 dqh_version; /* Quota format version */
+};
+
+/* Quota flags in dqinfo header */
+#define OLQF_CLEAN 0x0001 /* Quota file is empty (this should be after\
+ * quota has been cleanly turned off) */
+
+#define OCFS2_LOCAL_INFO_OFF (sizeof(struct ocfs2_disk_dqheader))
+
+/* Information header of local quota file (immediately follows the generic
+ * header) */
+struct ocfs2_local_disk_dqinfo {
+ __le32 dqi_flags; /* Flags for quota file */
+ __le32 dqi_chunks; /* Number of chunks of quota structures
+ * with a bitmap */
+ __le32 dqi_blocks; /* Number of blocks allocated for quota file */
+};
+
+/* Header of one chunk of a quota file */
+struct ocfs2_local_disk_chunk {
+ __le32 dqc_free; /* Number of free entries in the bitmap */
+ uint8_t dqc_bitmap[0]; /* Bitmap of entries in the corresponding
+ * chunk of quota file */
+};
+
+#define OCFS2_GLOBAL_INFO_OFF (sizeof(struct ocfs2_disk_dqheader))
+
+/* Information header of global quota file (immediately follows the generic
+ * header) */
+struct ocfs2_global_disk_dqinfo {
+ __le32 dqi_bgrace;
+ __le32 dqi_igrace;
+ __le32 dqi_syncms;
+ __le32 dqi_blocks;
+ __le32 dqi_free_blk;
+ __le32 dqi_free_entry;
+};
+
+/* Header of leaf tree block */
+struct ocfs2_disk_dqdbheader {
+ __le32 dqdh_next_free; /* Number of next block with free entry */
+ __le32 dqdh_prev_free; /* Number of previous block with free entry */
+ __le16 dqdh_entries; /* Number of valid entries in block */
+ __le16 dqdh_pad1;
+ __le32 dqdh_pad2;
+};
+
+/* Structure with global user / group information. We reserve some space
+ * for future use. */
+struct ocfs2_global_disk_dqblk {
+ __le32 dqb_id; /* ID the structure belongs to */
+ __le32 dqb_use_count; /* Number of nodes having reference to this structure */
+ __le64 dqb_ihardlimit; /* absolute limit on allocated inodes */
+ __le64 dqb_isoftlimit; /* preferred inode limit */
+ __le64 dqb_curinodes; /* current # allocated inodes */
+ __le64 dqb_bhardlimit; /* absolute limit on disk space */
+ __le64 dqb_bsoftlimit; /* preferred limit on disk space */
+ __le64 dqb_curspace; /* current space occupied */
+ __le64 dqb_btime; /* time limit for excessive disk use */
+ __le64 dqb_itime; /* time limit for excessive inode use */
+ __le64 dqb_pad1;
+ __le64 dqb_pad2;
+};
+
#ifdef __KERNEL__
static inline int ocfs2_fast_symlink_chars(struct super_block *sb)
{
diff --git a/include/ocfs2/ocfs2.h b/include/ocfs2/ocfs2.h
index 68ba4f5..cabae04 100644
--- a/include/ocfs2/ocfs2.h
+++ b/include/ocfs2/ocfs2.h
@@ -134,6 +134,16 @@ typedef struct _ocfs2_dir_scan ocfs2_dir_scan;
typedef struct _ocfs2_bitmap ocfs2_bitmap;
typedef struct _ocfs2_devices ocfs2_devices;
+#define MAXQUOTAS 2
+
+struct _ocfs2_quota_info {
+ uint32_t dqi_bgrace;
+ uint32_t dqi_igrace;
+ uint32_t dqi_syncms;
+};
+
+typedef struct _ocfs2_quota_info ocfs2_quota_info;
+
struct _ocfs2_filesys {
char *fs_devname;
uint32_t fs_flags;
@@ -160,6 +170,8 @@ struct _ocfs2_filesys {
struct o2dlm_ctxt *fs_dlm_ctxt;
struct ocfs2_image_state *ost;
+ ocfs2_quota_info qinfo[MAXQUOTAS];
+
/* Reserved for the use of the calling application. */
void *fs_private;
};
@@ -557,6 +569,19 @@ errcode_t ocfs2_meta_lock(ocfs2_filesys *fs, ocfs2_cached_inode *inode,
errcode_t ocfs2_meta_unlock(ocfs2_filesys *fs, ocfs2_cached_inode *ci);
+/* Quota operations */
+void ocfs2_swap_quota_header(struct ocfs2_disk_dqheader *header);
+void ocfs2_swap_quota_local_info(struct ocfs2_local_disk_dqinfo *info);
+void ocfs2_swap_quota_chunk_header(struct ocfs2_local_disk_chunk *chunk);
+void ocfs2_swap_quota_global_info(struct ocfs2_global_disk_dqinfo *info);
+void ocfs2_swap_quota_global_dqblk(struct ocfs2_global_disk_dqblk *dqblk);
+void ocfs2_swap_quota_leaf_block_header(struct ocfs2_disk_dqdbheader *bheader);
+errcode_t ocfs2_create_local_quota_file(ocfs2_filesys *fs, int type,
+ uint64_t blkno);
+int ocfs2_qtree_depth(int blocksize);
+errcode_t ocfs2_create_global_quota_file(ocfs2_filesys *fs, int type,
+ uint64_t blkno);
+
/* Low level */
void ocfs2_swap_slot_map(struct ocfs2_slot_map *sm, int num_slots);
void ocfs2_swap_slot_map_extended(struct ocfs2_slot_map_extended *se,
diff --git a/libocfs2/Makefile b/libocfs2/Makefile
index 446c8b4..18cf2ee 100644
--- a/libocfs2/Makefile
+++ b/libocfs2/Makefile
@@ -72,6 +72,7 @@ CFILES = \
lockid.c \
backup_super.c \
feature_string.c\
+ quota.c \
image.c
HFILES = \
diff --git a/libocfs2/feature_string.c b/libocfs2/feature_string.c
index 7b1f93e..00c4f26 100644
--- a/libocfs2/feature_string.c
+++ b/libocfs2/feature_string.c
@@ -73,7 +73,9 @@ static ocfs2_fs_options feature_level_defaults[] = {
OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC |
OCFS2_FEATURE_INCOMPAT_EXTENDED_SLOT_MAP |
OCFS2_FEATURE_INCOMPAT_INLINE_DATA,
- OCFS2_FEATURE_RO_COMPAT_UNWRITTEN}, /* OCFS2_FEATURE_LEVEL_MAX_FEATURES */
+ OCFS2_FEATURE_RO_COMPAT_UNWRITTEN |
+ OCFS2_FEATURE_RO_COMPAT_USRQUOTA |
+ OCFS2_FEATURE_RO_COMPAT_GRPQUOTA }, /* OCFS2_FEATURE_LEVEL_MAX_FEATURES */
};
/* These are the features we support in mkfs/tunefs via --fs-features */
@@ -110,6 +112,16 @@ static struct fs_feature_flags ocfs2_supported_features[] = {
{0, OCFS2_FEATURE_INCOMPAT_INLINE_DATA, 0},
},
{
+ "usrquota",
+ {0, 0, OCFS2_FEATURE_RO_COMPAT_USRQUOTA},
+ {0, 0, OCFS2_FEATURE_RO_COMPAT_USRQUOTA},
+ },
+ {
+ "grpquota",
+ {0, 0, OCFS2_FEATURE_RO_COMPAT_GRPQUOTA},
+ {0, 0, OCFS2_FEATURE_RO_COMPAT_GRPQUOTA},
+ },
+ {
NULL,
{0, 0, 0},
{0, 0, 0}
@@ -161,6 +173,14 @@ static struct feature_name ocfs2_feature_names[] = {
.fn_flag = {0, 0, OCFS2_FEATURE_RO_COMPAT_UNWRITTEN},
},
{
+ .fn_name = "UserQuota",
+ .fn_flag = {0, 0, OCFS2_FEATURE_RO_COMPAT_USRQUOTA},
+ },
+ {
+ .fn_name = "GroupQuota",
+ .fn_flag = {0, 0, OCFS2_FEATURE_RO_COMPAT_GRPQUOTA},
+ },
+ {
.fn_name = "InlineData",
.fn_flag = {0, OCFS2_FEATURE_INCOMPAT_INLINE_DATA, 0},
},
diff --git a/libocfs2/quota.c b/libocfs2/quota.c
new file mode 100644
index 0000000..8670ae0
--- /dev/null
+++ b/libocfs2/quota.c
@@ -0,0 +1,261 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * quota.c
+ *
+ * Quota operations for the OCFS2 userspace library.
+ *
+ * Copyright (C) 2008 Novell. 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.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ */
+
+#include <inttypes.h>
+
+#include "ocfs2/byteorder.h"
+#include "ocfs2/ocfs2.h"
+
+void ocfs2_swap_quota_header(struct ocfs2_disk_dqheader *header)
+{
+ if (cpu_is_little_endian)
+ return;
+ header->dqh_magic = bswap_32(header->dqh_magic);
+ header->dqh_version = bswap_32(header->dqh_version);
+}
+
+void ocfs2_swap_quota_local_info(struct ocfs2_local_disk_dqinfo *info)
+{
+ if (cpu_is_little_endian)
+ return;
+ info->dqi_flags = bswap_32(info->dqi_flags);
+ info->dqi_chunks = bswap_32(info->dqi_chunks);
+ info->dqi_blocks = bswap_32(info->dqi_blocks);
+}
+
+void ocfs2_swap_quota_chunk_header(struct ocfs2_local_disk_chunk *chunk)
+{
+ if (cpu_is_little_endian)
+ return;
+ chunk->dqc_free = bswap_32(chunk->dqc_free);
+}
+
+void ocfs2_swap_quota_global_info(struct ocfs2_global_disk_dqinfo *info)
+{
+ if (cpu_is_little_endian)
+ return;
+ info->dqi_bgrace = bswap_32(info->dqi_bgrace);
+ info->dqi_igrace = bswap_32(info->dqi_igrace);
+ info->dqi_syncms = bswap_32(info->dqi_syncms);
+ info->dqi_blocks = bswap_32(info->dqi_blocks);
+ info->dqi_free_blk = bswap_32(info->dqi_free_blk);
+ info->dqi_free_entry = bswap_32(info->dqi_free_entry);
+}
+
+void ocfs2_swap_quota_global_dqblk(struct ocfs2_global_disk_dqblk *dqblk)
+{
+ if (cpu_is_little_endian)
+ return;
+ dqblk->dqb_id = bswap_32(dqblk->dqb_id);
+ dqblk->dqb_use_count = bswap_32(dqblk->dqb_use_count);
+ dqblk->dqb_ihardlimit = bswap_64(dqblk->dqb_ihardlimit);
+ dqblk->dqb_isoftlimit = bswap_64(dqblk->dqb_isoftlimit);
+ dqblk->dqb_curinodes = bswap_64(dqblk->dqb_curinodes);
+ dqblk->dqb_bhardlimit = bswap_64(dqblk->dqb_bhardlimit);
+ dqblk->dqb_bsoftlimit = bswap_64(dqblk->dqb_bsoftlimit);
+ dqblk->dqb_curspace = bswap_64(dqblk->dqb_curspace);
+ dqblk->dqb_btime = bswap_64(dqblk->dqb_btime);
+ dqblk->dqb_itime = bswap_64(dqblk->dqb_itime);
+}
+
+void ocfs2_swap_quota_leaf_block_header(struct ocfs2_disk_dqdbheader *bheader)
+{
+ if (cpu_is_little_endian)
+ return;
+ bheader->dqdh_next_free = bswap_32(bheader->dqdh_next_free);
+ bheader->dqdh_prev_free = bswap_32(bheader->dqdh_prev_free);
+ bheader->dqdh_entries = bswap_16(bheader->dqdh_entries);
+}
+
+errcode_t ocfs2_create_local_quota_file(ocfs2_filesys *fs, int type,
+ uint64_t blkno)
+{
+ ocfs2_cached_inode *ci = NULL;
+ struct ocfs2_dinode *di;
+ struct ocfs2_disk_dqheader *header;
+ struct ocfs2_local_disk_dqinfo *info;
+ unsigned int magics[] = OCFS2_LOCAL_QMAGICS;
+ int versions[] = OCFS2_LOCAL_QVERSIONS;
+ char *buf = NULL;
+ unsigned int written;
+ errcode_t err;
+
+ err = ocfs2_read_cached_inode(fs, blkno, &ci);
+ if (err)
+ goto out;
+
+ if (!(ci->ci_inode->i_flags & OCFS2_VALID_FL) ||
+ !(ci->ci_inode->i_flags & OCFS2_SYSTEM_FL) ||
+ !(ci->ci_inode->i_flags & OCFS2_QUOTA_FL)) {
+ err = OCFS2_ET_INTERNAL_FAILURE;
+ goto out;
+ }
+ di = ci->ci_inode;
+
+ /* We need at least two blocks */
+ err = ocfs2_extend_allocation(fs, blkno, (2 * fs->fs_blocksize +
+ fs->fs_clustersize - 1) / fs->fs_clustersize);
+ if (err)
+ goto out;
+ di->i_size = 2 * fs->fs_blocksize;
+ di->i_mtime = time(NULL);
+ err = ocfs2_write_inode(fs, blkno, (char *)di);
+ if (err)
+ goto out;
+
+ err = ocfs2_malloc_blocks(fs->fs_io, fs->fs_blocksize * 2, &buf);
+ if (err)
+ goto out;
+ memset(buf, 0, 2 * fs->fs_blocksize);
+
+ header = (struct ocfs2_disk_dqheader *)buf;
+ header->dqh_magic = magics[type];
+ header->dqh_version = versions[type];
+ ocfs2_swap_quota_header(header);
+
+ info = (struct ocfs2_local_disk_dqinfo *)(buf + OCFS2_LOCAL_INFO_OFF);
+ info->dqi_chunks = 1;
+ info->dqi_blocks = 2;
+ info->dqi_flags = OLQF_CLEAN;
+ ocfs2_swap_quota_local_info(info);
+
+ /* There are no free chunks because there are no blocks allocated for
+ * them yet. So chunk header is all-zero and needs no initialization */
+
+ err = ocfs2_file_write(ci, buf, 2 * fs->fs_blocksize, 0, &written);
+ if (!err && written != 2 * fs->fs_blocksize) {
+ err = OCFS2_ET_INTERNAL_FAILURE;
+ goto out;
+ }
+out:
+ if (ci)
+ ocfs2_free_cached_inode(fs, ci);
+ if (buf)
+ ocfs2_free(&buf);
+ return err;
+}
+
+int ocfs2_qtree_depth(int blocksize)
+{
+ unsigned int epb = (blocksize - OCFS2_QBLK_RESERVED_SPACE) >> 2;
+ unsigned long long entries = epb;
+ int i;
+
+ for (i = 1; entries < (1ULL << 32); i++)
+ entries *= epb;
+ return i;
+}
+
+errcode_t ocfs2_create_global_quota_file(ocfs2_filesys *fs, int type,
+ uint64_t blkno)
+{
+ ocfs2_cached_inode *ci = NULL;
+ struct ocfs2_dinode *di;
+ char *buf = NULL;
+ struct ocfs2_disk_dqheader *header;
+ struct ocfs2_global_disk_dqinfo *info;
+ struct ocfs2_global_disk_dqblk *dqblk;
+ struct ocfs2_disk_dqdbheader *bheader;
+ uint32_t *treeblk;
+ unsigned int magics[] = OCFS2_GLOBAL_QMAGICS;
+ int versions[] = OCFS2_GLOBAL_QVERSIONS;
+ errcode_t err;
+ int blocks = ocfs2_qtree_depth(fs->fs_blocksize) + 2;
+ unsigned int written;
+ int i;
+
+ err = ocfs2_read_cached_inode(fs, blkno, &ci);
+ if (err)
+ goto out;
+
+ if (!(ci->ci_inode->i_flags & OCFS2_VALID_FL) ||
+ !(ci->ci_inode->i_flags & OCFS2_SYSTEM_FL) ||
+ !(ci->ci_inode->i_flags & OCFS2_QUOTA_FL)) {
+ err = OCFS2_ET_INTERNAL_FAILURE;
+ goto out;
+ }
+ di = ci->ci_inode;
+
+ err = ocfs2_extend_allocation(fs, blkno, (blocks * fs->fs_blocksize +
+ fs->fs_clustersize - 1) / fs->fs_clustersize);
+ if (err)
+ goto out;
+ di->i_size = blocks * fs->fs_blocksize;
+ di->i_mtime = time(NULL);
+ err = ocfs2_write_inode(fs, blkno, (char *)di);
+ if (err)
+ goto out;
+ err = ocfs2_malloc_blocks(fs->fs_io, fs->fs_blocksize * blocks, &buf);
+ if (err)
+ goto out;
+ memset(buf, 0, fs->fs_blocksize * blocks);
+
+ header = (struct ocfs2_disk_dqheader *)buf;
+ header->dqh_magic = magics[type];
+ header->dqh_version = versions[type];
+ ocfs2_swap_quota_header(header);
+
+ info = (struct ocfs2_global_disk_dqinfo *)(buf + OCFS2_GLOBAL_INFO_OFF);
+ info->dqi_bgrace = fs->qinfo[type].dqi_bgrace;
+ info->dqi_igrace = fs->qinfo[type].dqi_igrace;
+ info->dqi_syncms = fs->qinfo[type].dqi_syncms;
+ info->dqi_blocks = blocks;
+ info->dqi_free_blk = 0;
+ info->dqi_free_entry = blocks - 1;
+ ocfs2_swap_quota_global_info(info);
+
+ /* FIXME: This should be split into a separate function that is able to
+ * add blocks etc. Usage information can then be properly specified by
+ * the caller. */
+ /* Create quota structure for root user */
+ for (i = 0; i < ocfs2_qtree_depth(fs->fs_blocksize); i++) {
+ treeblk = (uint32_t *)(buf +
+ ((i + 1) * fs->fs_blocksize));
+ *treeblk = cpu_to_le32(i + 2);
+ }
+
+ bheader = (struct ocfs2_disk_dqdbheader *)(buf +
+ ((i + 1) * fs->fs_blocksize));
+ bheader->dqdh_entries = 1;
+ ocfs2_swap_quota_leaf_block_header(bheader);
+
+ dqblk = (struct ocfs2_global_disk_dqblk *)(buf +
+ ((i + 1) * fs->fs_blocksize) +
+ sizeof(struct ocfs2_disk_dqdbheader));
+ dqblk->dqb_curinodes = 2;
+ dqblk->dqb_curspace = 2 * fs->fs_blocksize;
+ ocfs2_swap_quota_global_dqblk(dqblk);
+
+ err = ocfs2_file_write(ci, buf, blocks * fs->fs_blocksize, 0, &written);
+ if (!err && written != blocks * fs->fs_blocksize) {
+ err = OCFS2_ET_INTERNAL_FAILURE;
+ goto out;
+ }
+out:
+ if (ci)
+ ocfs2_free_cached_inode(fs, ci);
+ if (buf)
+ ocfs2_free(&buf);
+ return err;
+}
diff --git a/mkfs.ocfs2/mkfs.c b/mkfs.ocfs2/mkfs.c
index aad166b..9fe2ac2 100644
--- a/mkfs.ocfs2/mkfs.c
+++ b/mkfs.ocfs2/mkfs.c
@@ -96,12 +96,16 @@ static SystemFileInfo system_files[] = {
{ "slot_map", SFI_OTHER, 1, S_IFREG | 0644 },
{ "heartbeat", SFI_HEARTBEAT, 1, S_IFREG | 0644 },
{ "global_bitmap", SFI_CLUSTER, 1, S_IFREG | 0644 },
+ { "aquota.user", SFI_QUOTA, 1, S_IFREG | 0644 },
+ { "aquota.group", SFI_QUOTA, 1, S_IFREG | 0644 },
{ "orphan_dir:%04d", SFI_OTHER, 0, S_IFDIR | 0755 },
{ "extent_alloc:%04d", SFI_CHAIN, 0, S_IFREG | 0644 },
{ "inode_alloc:%04d", SFI_CHAIN, 0, S_IFREG | 0644 },
{ "journal:%04d", SFI_JOURNAL, 0, S_IFREG | 0644 },
{ "local_alloc:%04d", SFI_LOCAL_ALLOC, 0, S_IFREG | 0644 },
- { "truncate_log:%04d", SFI_TRUNCATE_LOG, 0, S_IFREG | 0644 }
+ { "truncate_log:%04d", SFI_TRUNCATE_LOG, 0, S_IFREG | 0644 },
+ { "aquota%04d.user", SFI_QUOTA, 0, S_IFREG | 0644 },
+ { "aquota%04d.group", SFI_QUOTA, 0, S_IFREG | 0644 },
};
struct fs_type_translation {
@@ -184,6 +188,23 @@ static int hb_dev_skip(State *s, int system_inode)
return ret;
}
+/* Should we skip this inode because of features enabled / disabled? */
+static int feature_skip(State *s, int system_inode)
+{
+ switch (system_inode) {
+ case USER_QUOTA_SYSTEM_INODE:
+ case LOCAL_USER_QUOTA_SYSTEM_INODE:
+ return !(s->feature_flags.opt_ro_compat &
+ OCFS2_FEATURE_RO_COMPAT_USRQUOTA);
+ case GROUP_QUOTA_SYSTEM_INODE:
+ case LOCAL_GROUP_QUOTA_SYSTEM_INODE:
+ return !(s->feature_flags.opt_ro_compat &
+ OCFS2_FEATURE_RO_COMPAT_GRPQUOTA);
+ default:
+ return 0;
+ }
+}
+
static inline uint32_t system_dir_bytes_needed(State *s)
{
int each = OCFS2_DIR_REC_LEN(SYSTEM_FILE_NAME_MAX);
@@ -191,6 +212,108 @@ static inline uint32_t system_dir_bytes_needed(State *s)
return each * sys_blocks_needed(s->initial_slots);
}
+static void format_quota_files(State *s)
+{
+ errcode_t ret;
+ ocfs2_filesys *fs = NULL;
+ char fname[SYSTEM_FILE_NAME_MAX];
+ uint64_t blkno;
+ int i;
+
+ ret = ocfs2_open(s->device_name, OCFS2_FLAG_RW, 0, 0, &fs);
+ if (ret) {
+ com_err(s->progname, ret, "while opening new file system");
+ exit(1);
+ }
+
+ /* Write correct data into quota files */
+ if (!feature_skip(s, USER_QUOTA_SYSTEM_INODE)) {
+ fs->qinfo[0].dqi_syncms = 10000;
+ fs->qinfo[0].dqi_bgrace = 604800; /* 1 week */
+ fs->qinfo[0].dqi_igrace = 604800; /* 1 week */
+ snprintf(fname, sizeof(fname),
+ ocfs2_system_inodes[USER_QUOTA_SYSTEM_INODE].si_name);
+ ret = ocfs2_lookup(fs, fs->fs_sysdir_blkno, fname,
+ strlen(fname), NULL, &blkno);
+ if (ret) {
+ com_err(s->progname, ret,
+ "while looking up quota filename \"%.*s\"",
+ (int)strlen(fname), fname);
+ goto error;
+ }
+ ret = ocfs2_create_global_quota_file(fs, 0, blkno);
+ if (ret) {
+ com_err(s->progname, ret, "while creating global user "
+ "quota file");
+ goto error;
+ }
+ for (i = 0; i < s->initial_slots; ++i) {
+ snprintf(fname, sizeof(fname),
+ ocfs2_system_inodes[
+ LOCAL_USER_QUOTA_SYSTEM_INODE].si_name, i);
+ ret = ocfs2_lookup(fs, fs->fs_sysdir_blkno, fname,
+ strlen(fname), NULL, &blkno);
+ if (ret) {
+ com_err(s->progname, ret,
+ "while looking up quota filename "
+ "\"%.*s\"", (int)strlen(fname), fname);
+ goto error;
+ }
+ ret = ocfs2_create_local_quota_file(fs, 0, blkno);
+ if (ret) {
+ com_err(s->progname, ret, "while creating "
+ "local user quota file");
+ goto error;
+ }
+ }
+ }
+ if (!feature_skip(s, GROUP_QUOTA_SYSTEM_INODE)) {
+ fs->qinfo[1].dqi_syncms = 10000;
+ fs->qinfo[1].dqi_bgrace = 604800; /* 1 week */
+ fs->qinfo[1].dqi_igrace = 604800; /* 1 week */
+ snprintf(fname, sizeof(fname),
+ ocfs2_system_inodes[GROUP_QUOTA_SYSTEM_INODE].si_name);
+ ret = ocfs2_lookup(fs, fs->fs_sysdir_blkno, fname,
+ strlen(fname), NULL, &blkno);
+ if (ret) {
+ com_err(s->progname, ret,
+ "while looking up quota filename \"%.*s\"",
+ (int)strlen(fname), fname);
+ goto error;
+ }
+ ret = ocfs2_create_global_quota_file(fs, 1, blkno);
+ if (ret) {
+ com_err(s->progname, ret, "while creating global group "
+ "quota file");
+ goto error;
+ }
+ for (i = 0; i < s->initial_slots; ++i) {
+ snprintf(fname, sizeof(fname),
+ ocfs2_system_inodes[
+ LOCAL_GROUP_QUOTA_SYSTEM_INODE].si_name, i);
+ ret = ocfs2_lookup(fs, fs->fs_sysdir_blkno, fname,
+ strlen(fname), NULL, &blkno);
+ if (ret) {
+ com_err(s->progname, ret,
+ "while looking up quota filename "
+ "\"%.*s\"", (int)strlen(fname), fname);
+ goto error;
+ }
+ ret = ocfs2_create_local_quota_file(fs, 1, blkno);
+ if (ret) {
+ com_err(s->progname, ret, "while creating "
+ "local group quota file");
+ goto error;
+ }
+ }
+ }
+ ocfs2_close(fs);
+ return;
+error:
+ clear_both_ends(s);
+ exit(1);
+}
+
int
main(int argc, char **argv)
{
@@ -355,6 +478,8 @@ main(int argc, char **argv)
for (i = 0; i < NUM_SYSTEM_INODES; i++) {
if (hb_dev_skip(s, i))
continue;
+ if (feature_skip(s, i))
+ continue;
num = (system_files[i].global) ? 1 : s->initial_slots;
for (j = 0; j < num; j++) {
@@ -413,6 +538,8 @@ main(int argc, char **argv)
for (i = 0; i < NUM_SYSTEM_INODES; i++) {
if (hb_dev_skip(s, i))
continue;
+ if (feature_skip(s, i))
+ continue;
num = system_files[i].global ? 1 : s->initial_slots;
for (j = 0; j < num; j++) {
@@ -496,6 +623,14 @@ main(int argc, char **argv)
if (!s->quiet)
printf("done\n");
+
+ if (!s->quiet)
+ printf("Formatting quota files: ");
+
+ format_quota_files(s);
+
+ if (!s->quiet)
+ printf("done\n");
}
close_device(s);
@@ -2304,6 +2439,9 @@ init_record(State *s, SystemFileDiskRecord *rec, int type, int mode)
case SFI_TRUNCATE_LOG:
rec->flags |= OCFS2_DEALLOC_FL;
break;
+ case SFI_QUOTA:
+ rec->flags |= OCFS2_QUOTA_FL;
+ break;
case SFI_OTHER:
break;
}
diff --git a/mkfs.ocfs2/mkfs.h b/mkfs.ocfs2/mkfs.h
index bd8ac45..969e4df 100644
--- a/mkfs.ocfs2/mkfs.h
+++ b/mkfs.ocfs2/mkfs.h
@@ -96,6 +96,7 @@ enum {
SFI_HEARTBEAT,
SFI_CHAIN,
SFI_TRUNCATE_LOG,
+ SFI_QUOTA,
SFI_OTHER
};
diff --git a/o2image/Makefile b/o2image/Makefile
index 0259161..b50201a 100644
--- a/o2image/Makefile
+++ b/o2image/Makefile
@@ -32,6 +32,6 @@ OBJS = $(subst .c,.o,$(CFILES))
DIST_FILES = $(CFILES) $(HFILES) o2image.8.in
o2image: $(OBJS) $(LIBOCFS2_DEPS)
- $(LINK) $(GLIB_LIBS) $(LIBOCFS2_LIBS) $(COM_ERR_LIBS)
+ $(LINK) -static $(GLIB_LIBS) $(LIBOCFS2_LIBS) $(COM_ERR_LIBS) -lpthread
include $(TOPDIR)/Postamble.make
--
1.5.2.4

View File

@ -1,12 +0,0 @@
Index: o2image/Makefile
===================================================================
--- o2image/Makefile.orig
+++ o2image/Makefile
@@ -32,6 +32,6 @@ OBJS = $(subst .c,.o,$(CFILES))
DIST_FILES = $(CFILES) $(HFILES) o2image.8.in
o2image: $(OBJS) $(LIBOCFS2_DEPS)
- $(LINK) -static $(GLIB_LIBS) $(LIBOCFS2_LIBS) $(COM_ERR_LIBS) -lpthread
+ $(LINK) -static $(GLIB_LIBS) $(LIBOCFS2_LIBS) -Wl,-Bdynamic $(COM_ERR_LIBS) -lpthread
include $(TOPDIR)/Postamble.make

View File

@ -1,12 +0,0 @@
Index: ocfs2-tools/ocfs2_controld/main.c
===================================================================
--- ocfs2-tools.orig/ocfs2_controld/main.c
+++ ocfs2-tools/ocfs2_controld/main.c
@@ -34,6 +34,7 @@
#include <sys/socket.h>
#include <signal.h>
#include <syslog.h>
+#include <limits.h>
#include <sched.h>
#include "ocfs2-kernel/kernel-list.h"

View File

@ -1,29 +1,242 @@
-------------------------------------------------------------------
Sun Apr 18 16:10:28 UTC 2010 - crrodriguez@opensuse.org
Mon Jun 14 15:19:45 UTC 2010 - lmb@novell.com
- Requires timezone
- ocfs2_controld.pcmk: compilation issue fixed.
-------------------------------------------------------------------
Fri Apr 9 07:25:41 UTC 2010 - aj@suse.de
Mon Apr 26 14:43:04 UTC 2010 - coyli@novell.com
- Fix build.
- fixes for indexed-dirs
- 0016-tunefs.ocfs2-move-o2ne_add_tailers-into-libocfs2ne.c.patch
- 0017-dx_dirs-add-check-for-invalid-slot-in-ocfs2_new_dx_r.patch
- 0018-mkfs.ocfs2-create-root-and-orphan-directories-as-ind.patch
- 0019-libocfs2-fix-flag-check-in-ocfs2_init_dir.patch
- 0020-libocfs2-fix-ocfs2_init_dir-to-retain-indexed-flag.patch
- 0021-fsck.ocfs2-verify-dirent-dx-entry-linkages.patch
- 0022-dx_dirs-stop-iterate-dir-entries-for-I-O-error.patch
- 0023-dx_dirs-check-callback-iter-dx_func-return-value-in-.patch
- 0024-dx_dirs-remove-unncessary-return-value-assignment.patch
- 0025-dx_dirs-unifiy-feature-string-of-indexed-dirs.patch
- 0026-dx_dirs-Improve-information-displayed-by-dump_dx_roo.patch
- 0027-dx_dirs-stop-iteration-of-dir-trailer-initialization.patch
- 0028-dx_dirs-stop-dx-insert-iteration-for-callback-error.patch
- 0029-dx_dirs-set-OCFS2_INDEXED_DIR_FL-after-indexed-tree-.patch
- 0030-dx_dirs-fix-ocfs2_swap_dx_entry_list-for-big-endian.patch
-------------------------------------------------------------------
Wed Sep 30 08:03:29 UTC 2009 - aj@suse.de
Sun Apr 11 20:06:09 CST 2010 - coyli@novell.com
- Do not require ocfs-kmp for openSUSE 11.2.
- update indexed-dirs patches to v11 patches
- a bug fix in fsck.ocfs2/pass2.c
- extra check whether the directory trailer overwrites valid
directory items.
-------------------------------------------------------------------
Mon Jul 13 16:57:52 CEST 2009 - coolo@novell.com
Thu Apr 8 17:19:21 UTC 2010 - lmb@novell.com
- fix build with e2fsprogs
- fix build with glibc 2.10
- fix build with as-needed
- Add reflink user-space utility to expose the copy-on-write links in
OCFS2 for all platforms (bnc#594979).
-------------------------------------------------------------------
Thu Apr 16 01:40:48 CEST 2009 - ro@suse.de
Thu Mar 25 19:17:55 UTC 2010 - coyli@novell.com
- buildfix: refresh patches
- 0015-dx_dirs-enable-metaecc-and-indexed-dirs-support-as-d.patch:
enable metaecc and indexed-dirs support as default features.
- ocfs2-tools-static-glib.diff: rename to ocfs2-o2cb_ctl-static-glibc.diff,
don't explicitly link pthread anymore.
- update ocfs2-tools.tar.bz2 to upstream (0a1c1970):
- mkfs.ocfs2: enable xattr support as a default feature
- Fsck.ocfs2: Correctly check i_size for directory in a sparse
filesystem.
- fsck.ocfs2: Freshen up some fsck messages
- mkfs.ocfs2: Add dry-run option
- mkfs.ocfs2: Allocate groups to the extent allocator
- libocfs2: Add ocfs2_grow_chain_allocator()
- libocfs2: ocfs2_chain_add_group() adds new groups to the next
logical chain
- mounted.ocfs2: Add the stack/local to the output
- mounted.ocfs2: Display uuid in all caps
- mkfs.ocfs2: Tweak the feature compatibility list in manpage
- mkfs.ocfs2: Print fs features during make
-------------------------------------------------------------------
Fri Mar 12 06:32:34 UTC 2010 - coyli@novell.com
- 0014-dx_dirs-man-page.diff: add an initial man page entry for
indexed-dirs feature.
-------------------------------------------------------------------
Thu Mar 11 16:41:09 UTC 2010 - coyli@novell.com
- bug-585080-handle-symbolic-link.patch: handle symbolic link device
file for tunefs.ocfs2 online resize (bnc#585080)
-------------------------------------------------------------------
Thu Mar 11 02:50:57 UTC 2010 - coyli@novell.com
- version-1.4.3.patch: keep package version as 1.4.3 for SLES11 HAE SP1.
-------------------------------------------------------------------
Thu Mar 11 01:04:34 UTC 2010 - coyli@novell.com
- 0013-dx_dirs-try-to-install-dir-trailers-when-enable-inde.patch: try
to install dir trailers when enable indexed-dirs feature while
metaecc features is not enabled. The fix can avoid ocfs2_dx_dir_build()
in ocfs2-tools to overwrite existed dir entries lying in trailer area
by moving them into other dir blocks. No BNC associated.
-------------------------------------------------------------------
Fri Mar 5 09:13:30 UTC 2010 - coyli@novell.com
- update indexed-dirs patches for
- remove the metaecc dependence code for indexed dirs. (bnc#584578)
- indexed dirs does not depend on metaecc, remove all
incorrect dependence code in mkfs.ocfs2 and tunefs.ocfs2 (bnc#585418)
- code clean up in mkfs.ocfs2
- back port ocfs2-tools version 1.6 to SP1 ocfs2-tools package.
-------------------------------------------------------------------
Wed Mar 3 09:51:32 UTC 2010 - coyli@novell.com
- add 0012-dx_dirs-fix-for-tunefs-metaecc-and-indexed-dirs.patch
(bnc#584578)
-------------------------------------------------------------------
Mon Feb 22 18:40:29 UTC 2010 - coyli@novell.com
- update indexed dirs patches for fate#300315
-------------------------------------------------------------------
Fri Feb 5 10:25:07 UTC 2010 - coyli@novell.com
- delete 64bytes_lvb_len_in_libo2dlm.diff (bnc#573460)
-------------------------------------------------------------------
Fri Jan 29 01:01:49 UTC 2010 - coyli@novell.com
- update indexed dirs patches.
-------------------------------------------------------------------
Thu Jan 28 21:01:02 UTC 2010 - coyli@novell.com
- compiling fix
-------------------------------------------------------------------
Thu Jan 28 20:52:10 UTC 2010 - coyli@novell.com
- add disable indexed-dirs support in tunefs.ocfs2 (fate#300315)
- more fixes for previous indexed-dirs patches
-------------------------------------------------------------------
Thu Jan 28 04:07:37 UTC 2010 - coyli@novell.com
- add the first version of indexed dir support (fate#300315)
-------------------------------------------------------------------
Mon Jan 25 16:23:47 UTC 2010 - lmb@novell.com
- ocfs2-tools requires openais for the user-space cluster stack.
-------------------------------------------------------------------
Wed Dec 9 09:47:31 UTC 2009 - "lmb@novell.com"
- Fix ocfs2-tools build (bnc#561625).
-------------------------------------------------------------------
Tue Dec 8 14:42:05 UTC 2009 - "lmb@novell.com"
- Add libcorosync-devel build dependency.
-------------------------------------------------------------------
Tue Dec 8 06:44:41 UTC 2009 - coyli@novell.com
- 64bytes_lvb_len_in_libo2dlm.diff: use 64 bytes lvb len ((bnc#515645))
-------------------------------------------------------------------
Thu Nov 26 06:17:33 UTC 2009 - coyli@novell.com
- change version number to 1.4.3
-------------------------------------------------------------------
Thu Nov 26 06:12:43 UTC 2009 - coyli@novell.com
- update ocfs2-tools-1.4.3 to SLES11SP1
-------------------------------------------------------------------
Tue Nov 3 16:34:52 UTC 2009 - coyli@novell.com
- bug-543119-o2dlm.patch: load libdlm_lt.so.3 explicitly in o2dlm.c (bnc#543119)
- drop bug-543119_0001-Option-to-skip-cluster-checking-in-tunefs.ocfs2.patch since
bnc#543119 is a dlopen() issue, and this patch is not accepted by upstream.
-------------------------------------------------------------------
Wed Oct 14 09:20:32 UTC 2009 - "lmb@novell.com"
- Implement a -F/--force option to bypass the cluster stack in
tunefs.ocfs2 (bnc#543119).
-------------------------------------------------------------------
Thu Sep 10 15:57:38 CEST 2009 - coly.li@suse.de
- fix kill_deamon() from o2cb.ocf, now when the deamon to be killed
is not running, kill_deamon() will return SUCESS. Thanks to Dejan.
-------------------------------------------------------------------
Tue Aug 4 20:34:25 CST 2009 - coly.li@suse.de
- add quota patches from Jan Kara, full support for enabling, disabling
and checking quotas.
-------------------------------------------------------------------
Tue Jul 28 21:26:27 CST 2009 - coly.li@suse.de
- Update code to upstream 1.4.2, to support xattr and acl in sles11
(bnc#499278), thanks to Goldwyn Rodrigues.
-------------------------------------------------------------------
Mon Mar 30 12:45:00 CEST 2009 - lmb@suse.de
- bug-478794-ocfs2_hb_ctl.diff: Fix crash on parsing corrupt file
systems (bnc#478794)
- debug-ocfs2_hb_ctl.patch: Better error logging.
-------------------------------------------------------------------
Fri Mar 20 12:17:02 CET 2009 - abeekhof@suse.de
- Fix the logging of calls to crm_terminate_member_no_mainloop()
-------------------------------------------------------------------
Tue Mar 17 23:25:00 CET 2009 - lmb@suse.de
- ocfs2_controld.pcmk crashed immediately on x86-64 (bnc#486104)
-------------------------------------------------------------------
Mon Mar 16 14:45:00 CET 2009 - lmb@suse.de
- ocfs2_controld-retry-470741.diff: removed.
- bug-470741_000{1,2,3}-ocfs2_controld.patch: retry most CKPT operations
forever, and recover from partially installed checkpoints
(bnc#470741).
-------------------------------------------------------------------
Thu Mar 12 14:34:26 CET 2009 - abeekhof@suse.de
- Use a Pacemaker library function for kicking nodes form the cluster
-------------------------------------------------------------------
Wed Mar 11 11:09:11 CET 2009 - abeekhof@suse.de
- Add some extra logging for bnc#484028
-------------------------------------------------------------------
Tue Mar 10 22:25:33 CET 2009 - abeekhof@suse.de
- Allow debug message to been seen in syslog for bnc#484028
-------------------------------------------------------------------
Thu Mar 05 09:00:00 CET 2009 - lmb@suse.de
- Adjust packaging split.
-------------------------------------------------------------------
Fri Feb 27 03:53:53 CET 2009 - coyli@suse.de

View File

@ -1,5 +1,5 @@
#
# spec file for package ocfs2-tools (Version 1.4.1)
# spec file for package ocfs2-tools (Version 1.4.3)
#
# Copyright (c) 2010 SUSE LINUX Products GmbH, Nuernberg, Germany.
#
@ -19,37 +19,63 @@
Name: ocfs2-tools
BuildRequires: e2fsprogs-devel glib2-devel libcom_err-devel libdlm-devel libopenais-devel libpacemaker-devel libxml2-devel libxslt-devel python-devel python-gtk-devel readline-devel update-desktop-files
BuildRequires: e2fsprogs-devel glib2-devel libcorosync-devel libdlm-devel libopenais-devel libpacemaker-devel libxml2-devel libxslt-devel python-devel python-gtk-devel readline-devel update-desktop-files
Summary: Oracle Cluster File System 2 Core Tools
Version: 1.4.1
Release: 25
License: GPLv2+
Version: 1.4.3
Release: 0.<RELEASE1>
License: GPL v2 or later
Group: System/Filesystems
Source: ocfs2-tools.tar.bz2
Source1: o2cb.ocf
Patch5: ocfs2-tools-static-glib.diff
Patch6: ocfs2console-display-fix.diff
Patch7: ocfs2-tools-glibc210.diff
Patch99: ocfs2-devel.diff
Patch100: ocfs2-quota.diff
Patch101: change-quotafile-names.diff
Patch102: ocfs2_controld-pacemaker.diff
Patch103: ocfs2console-extraoption-fix.diff
Patch104: ocfs2console-pop-display-warning.diff
Patch105: ocfs2_controld-retry-470741.diff
Patch106: tunefs.ocfs2.8.in_more_options.diff
Patch107: ocfs2-mount-gcc45.patch
Patch108: ocfs2-tools-dynamic-com-err.patch
Source2: reflink.tar.bz2
Patch101: ocfs2-o2cb_ctl-static-glibc.diff
Patch102: force-debug.patch
Patch103: extra-debug.patch
Patch104: debug-ocfs2_hb_ctl.patch
Patch105: ocfs2_controld-pacemaker.diff
Patch106: bug-470741-debug_start_failures.patch
Patch107: ocfs2-devel.diff
Patch201: bug-543119-o2dlm.patch
Patch202: bug-585080-handle-symbolic-link.patch
Patch301: 0001-dx_dirs-Add-library-support-for-directory-indexing.patch
Patch302: 0002-dx_dirs-debugfs.ocfs2-support.patch
Patch303: 0003-dx_dirs-mkfs.ocfs2-support.patch
Patch304: 0004-dx_dirs-Add-tunefs.ocfs2-feature-for-indexed-directo.patch
Patch305: 0005-dx_dirs-Update-for-dr_num_entries.patch
Patch306: 0006-dx_dirs-add-missing-ocfs2_filesys-fs-parameter.patch
Patch307: 0007-dx_dirs-more-library-support-for-directory-indexing.patch
Patch308: 0008-dx_dirs-fsck.ocfs2-support.patch
Patch309: 0009-dx_dirs-add-blocknr-in-callback-of-ocfs2_dir_iterate.patch
Patch310: 0010-dx_dirs-add-disable-indexed-dirs-support-in-tunefs.o.patch
Patch311: 0011-dx_dirs-build-indexed-trees-when-enabling-indexed-di.patch
Patch312: 0012-dx_dirs-fix-return-value-of-walk_dirblock-when-enabl.patch
Patch313: 0013-dx_dirs-try-to-install-dir-trailers-when-enable-inde.patch
Patch314: 0014-dx_dirs-add-an-initial-man-page-entry-for-indexed-di.patch
Patch315: 0015-fsck.ocfs2-prompt-before-truncating-an-invalid-dir-i.patch
Patch316: 0016-tunefs.ocfs2-move-o2ne_add_tailers-into-libocfs2ne.c.patch
Patch317: 0017-dx_dirs-add-check-for-invalid-slot-in-ocfs2_new_dx_r.patch
Patch318: 0018-mkfs.ocfs2-create-root-and-orphan-directories-as-ind.patch
Patch319: 0019-libocfs2-fix-flag-check-in-ocfs2_init_dir.patch
Patch320: 0020-libocfs2-fix-ocfs2_init_dir-to-retain-indexed-flag.patch
Patch321: 0021-fsck.ocfs2-verify-dirent-dx-entry-linkages.patch
Patch322: 0022-dx_dirs-stop-iterate-dir-entries-for-I-O-error.patch
Patch323: 0023-dx_dirs-check-callback-iter-dx_func-return-value-in-.patch
Patch324: 0024-dx_dirs-remove-unncessary-return-value-assignment.patch
Patch325: 0025-dx_dirs-unifiy-feature-string-of-indexed-dirs.patch
Patch326: 0026-dx_dirs-Improve-information-displayed-by-dump_dx_roo.patch
Patch327: 0027-dx_dirs-stop-iteration-of-dir-trailer-initialization.patch
Patch328: 0028-dx_dirs-stop-dx-insert-iteration-for-callback-error.patch
Patch329: 0029-dx_dirs-set-OCFS2_INDEXED_DIR_FL-after-indexed-tree-.patch
Patch330: 0030-dx_dirs-fix-ocfs2_swap_dx_entry_list-for-big-endian.patch
Patch331: 0031-dx_dirs-enable-metaecc-and-indexed-dirs-support-as-d.patch
Patch401: version-1.4.3.patch
Patch402: reflink-no-syscall.patch
Url: http://oss.oracle.com/projects/ocfs2-tools/
Requires: net-tools, modutils, e2fsprogs, /sbin/chkconfig, glib2 >= 2.2.3
PreReq: %insserv_prereq %fillup_prereq
AutoReqProv: on
BuildRoot: %{_tmppath}/%{name}-%{version}-build
Requires: libdlm timezone
%if %suse_version < 1120
# There's no separate kmp for openSUSE 11.2
Requires: ocfs2-kmp
%endif
Requires: libdlm ocfs2-kmp openais
%description
OCFS is the Oracle Cluster File System.
@ -64,7 +90,7 @@ Authors:
Oracle Corporation
%package -n ocfs2console
License: GPLv2+
License: GPL v2 or later
Summary: Oracle Cluster Filesystem 2 GUI tools
Group: System/Filesystems
Obsoletes: ocfs2-support
@ -84,7 +110,7 @@ Authors:
Oracle Corporation
%package devel
License: GPLv2+
License: GPL v2 or later
Summary: Oracle Cluster File System 2 Development files
Group: System/Filesystems
Requires: ocfs2-tools = %{version}, libcom_err, libcom_err-devel
@ -102,7 +128,7 @@ Authors:
Oracle Corporation
%package o2cb
License: GPLv2+
License: GPL v2 or later
Summary: Oracle Cluster File System 2 Core Tools
Group: System/Filesystems
Requires: ocfs2-tools = %{version}
@ -120,34 +146,66 @@ Authors:
Oracle Corporation
%prep
%setup -n %{name}
%patch5 -p1
%patch6 -p1
%patch7 -p1
%patch99 -p1
%patch100 -p1
%setup -n %{name} -a 2
%patch101 -p1
%patch102 -p1
%patch103 -p1
%patch104 -p1
%patch105 -p1
%patch106 -p1
%patch107 -p0
%patch108 -p0
%patch107 -p1
%patch201 -p1
%patch202 -p1
%patch301 -p1
%patch302 -p1
%patch303 -p1
%patch304 -p1
%patch305 -p1
%patch306 -p1
%patch307 -p1
%patch308 -p1
%patch309 -p1
%patch310 -p1
%patch311 -p1
%patch312 -p1
%patch313 -p1
%patch314 -p1
%patch315 -p1
%patch316 -p1
%patch317 -p1
%patch318 -p1
%patch319 -p1
%patch320 -p1
%patch321 -p1
%patch322 -p1
%patch323 -p1
%patch324 -p1
%patch325 -p1
%patch326 -p1
%patch327 -p1
%patch328 -p1
%patch329 -p1
%patch330 -p1
%patch331 -p1
%patch401 -p1
%patch402 -p0
%build
# disable as-needed to fix configure checks
export SUSE_ASNEEDED=0
%{?suse_update_config:%{suse_update_config -f}}
export CFLAGS="${CFLAGS} ${RPM_OPT_FLAGS}"
export PROJECT="ocfs2-tools"
autoreconf -fi -I /usr/share/aclocal
%configure --disable-debug --prefix=/usr --mandir=%{_mandir} \
--enable-dynamic-fsck=yes --enable-dynamic-ctl=yes
%configure --disable-debug --prefix=/usr --mandir=%{_mandir} --enable-dynamic-fsck=yes --enable-dynamic-ctl=yes
make OPTS="$RPM_OPT_FLAGS"
cd reflink
%configure --prefix=/usr --mandir=%{_mandir}
make reflink
cd ..
%install
mkdir -p $RPM_BUILD_ROOT/sbin
mkdir -p $RPM_BUILD_ROOT/usr/bin
mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/init.d
mkdir -p ${RPM_BUILD_ROOT}/var/adm/fillup-templates
mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/udev/rules.d/
@ -161,6 +219,11 @@ cp -f vendor/common/o2cb.sysconfig ${RPM_BUILD_ROOT}/var/adm/fillup-templates/sy
ln -sf ..%{_sysconfdir}/init.d/o2cb $RPM_BUILD_ROOT/sbin/rco2cb
ln -sf ..%{_sysconfdir}/init.d/ocfs2 $RPM_BUILD_ROOT/sbin/rcocfs2
make DESTDIR="$RPM_BUILD_ROOT" install
cd reflink
make DESTDIR="$RPM_BUILD_ROOT" install
cd ..
mv $RPM_BUILD_ROOT/{,/usr}/sbin/o2image
mv $RPM_BUILD_ROOT/{,/usr}/sbin/debugfs.ocfs2
mv $RPM_BUILD_ROOT/{,/usr}/sbin/ocfs2_controld.pcmk
@ -196,9 +259,11 @@ fi
/sbin/mounted.ocfs2
/sbin/tunefs.ocfs2
/sbin/mount.ocfs2
/sbin/ocfs2_hb_ctl
%{_sbindir}/o2image
%{_sbindir}/debugfs.ocfs2
%{_sbindir}/ocfs2_controld.pcmk
%{_bindir}/reflink
%config %{_sysconfdir}/udev/rules.d/51-ocfs2.rules
%{_mandir}/man8/debugfs.ocfs2.8*
%{_mandir}/man8/fsck.ocfs2.8*
@ -206,9 +271,10 @@ fi
%{_mandir}/man8/mkfs.ocfs2.8*
%{_mandir}/man8/tunefs.ocfs2.8*
%{_mandir}/man8/mounted.ocfs2.8*
%{_mandir}/man8/ocfs2_hb_ctl.8*
%{_mandir}/man8/mount.ocfs2.8*
%{_mandir}/man8/o2image.8.gz
%doc README.O2CB COPYING CREDITS MAINTAINERS
%doc COPYING CREDITS MAINTAINERS
%doc documentation/users_guide.txt
%dir /usr/lib/ocf
%dir /usr/lib/ocf/resource.d
@ -226,13 +292,12 @@ fi
/sbin/rco2cb
/sbin/rcocfs2
/sbin/o2cb_ctl
/sbin/ocfs2_hb_ctl
%{_sysconfdir}/init.d/o2cb
%{_sysconfdir}/init.d/ocfs2
%{_mandir}/man8/o2cb_ctl.8*
%{_mandir}/man8/ocfs2_hb_ctl.8*
/var/adm/fillup-templates/sysconfig.o2cb
%{_mandir}/man7/o2cb.7.gz
%doc README.O2CB
%files devel
%defattr(-,root,root)

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:147650748b00a969091b68886cfbaf1dea85e6912f709a76ab599f00ad576ece
size 1103130
oid sha256:c86b31db7cd2df1f711b977462c47889241a28b907de081c666ed8db7baccf29
size 1206555

View File

@ -1,487 +1,26 @@
diff --git a/ocfs2_controld/pacemaker.c b/ocfs2_controld/pacemaker.c
--- a/ocfs2_controld/pacemaker.c
+++ b/ocfs2_controld/pacemaker.c
@@ -20,20 +20,31 @@
#include <unistd.h>
#include <syslog.h>
-#include <crm/crm.h>
-#include <crm/common/cluster.h>
-#include <fencing/stonithd_api.h>
+#include <bzlib.h>
+
+#include <pacemaker/crm_config.h>
+
+/* heartbeat support is irrelevant here */
+#undef SUPPORT_HEARTBEAT
+#define SUPPORT_HEARTBEAT 0
+
+#include <pacemaker/crm/crm.h>
+#include <pacemaker/crm/ais.h>
+#include <pacemaker/crm/attrd.h>
+#include <pacemaker/crm/common/cluster.h>
+#include <pacemaker/crm/common/stack.h>
Index: ocfs2-tools/ocfs2_controld/pacemaker.c
===================================================================
--- ocfs2-tools.orig/ocfs2_controld/pacemaker.c
+++ ocfs2-tools/ocfs2_controld/pacemaker.c
@@ -31,6 +31,8 @@
#include <pacemaker/crm/ais.h>
#include <pacemaker/crm/common/cluster.h>
#include <pacemaker/crm/common/stack.h>
+#include <pacemaker/crm/common/ipc.h>
+#include <pacemaker/crm/msg_xml.h>
#include "ocfs2-kernel/kernel-list.h"
#include "o2cb/o2cb.h"
#include "ocfs2_controld.h"
-#include <bzlib.h>
-#include <crm/crm.h>
-#include <crm/ais.h>
#include <sys/utsname.h>
+#define log_printf(level, format, args...) syslog(level, "%s:%d " format "\n", __FILE__, __LINE__, ##args)
+
int our_nodeid = 0;
static int pcmk_ci;
static int stonithd_ci;
@@ -44,29 +55,57 @@ const char *stackname = "pcmk";
extern int ais_fd_async;
char *local_node_uname = NULL;
-int kill_stack_node(int nodeid)
-{
- int error = 1;
- stonith_ops_t st_op;
- char *target = nodeid2name(nodeid);
-
- log_debug("killing node %d (aka. %s)", nodeid, target);
-
- if(target) {
- st_op.timeout = 150;
- st_op.node_uuid = NULL;
- st_op.private_data = NULL;
- st_op.node_name = target;
- st_op.optype = POWEROFF;
-
- error = stonithd_node_fence(&st_op);
- }
+static IPC_Channel *attrd = NULL;
- if (error)
- log_debug("Unable to kill node %d, %d %d", nodeid, error,
- errno);
+static void attrd_deadfn(int ci)
+{
+ log_printf(LOG_ERR, "Lost connection to attrd");
+ attrd = NULL;
+ return;
+}
- return error;
+int kill_stack_node(int nodeid)
+{
+ gboolean rc = FALSE;
+ xmlNode *update = NULL;
+ time_t now = time(NULL);
+ crm_node_t *node = crm_get_peer(nodeid, NULL);
+
+ if(node == NULL || node->uname == NULL) {
+ log_printf(LOG_ERR, "%s: Don't know how to kick node %d/%p", __FUNCTION__, nodeid, node);
+ return -1;
+ }
+
+ if(attrd == NULL) {
+ log_printf(LOG_INFO, "Connecting to attrd...");
+ attrd = init_client_ipc_comms_nodispatch(T_ATTRD);
+ if(attrd) {
+ connection_add(attrd->ops->get_recv_select_fd(attrd), NULL, attrd_deadfn);
+ }
+ }
+
+ if(attrd != NULL) {
+ update = create_xml_node(NULL, __FUNCTION__);
+ crm_xml_add(update, F_TYPE, T_ATTRD);
+ crm_xml_add(update, F_ORIG, crm_system_name);
+
+ crm_xml_add(update, F_ATTRD_TASK, "update");
+ crm_xml_add(update, F_ATTRD_SECTION, XML_CIB_TAG_STATUS);
+ crm_xml_add(update, F_ATTRD_ATTRIBUTE, "terminate");
+ crm_xml_add_int(update, F_ATTRD_VALUE, now);
+ crm_xml_add(update, F_ATTRD_HOST, node->uname);
+
+ rc = send_ipc_message(attrd, update);
+ free_xml(update);
+ }
+
+ if(rc) {
+ log_printf(LOG_INFO, "Requested that node %d/%s be kicked from the cluster", nodeid, node->uname);
+ return 1;
+ }
+
+ log_printf(LOG_ERR, "Could not kick node %d/%s from the cluster", nodeid, node->uname);
+ return 0;
}
char *nodeid2name(int nodeid) {
@@ -81,7 +120,7 @@ char *nodeid2name(int nodeid) {
int validate_cluster(const char *cluster)
{
if (!clustername) {
- log_error("Trying to validate before pacemaker is alive");
+ log_printf(LOG_ERR, "Trying to validate before pacemaker is alive");
return 0;
}
@@ -94,12 +133,12 @@ int validate_cluster(const char *cluster)
int get_clustername(const char **cluster)
{
if (!clustername) {
- log_error("Trying to validate before pacemaker is alive");
+ log_printf(LOG_ERR, "Trying to validate before pacemaker is alive");
return -EIO;
}
if (!cluster) {
- log_error("NULL passed!");
+ log_printf(LOG_ERR, "NULL passed!");
return -EINVAL;
}
@@ -110,316 +149,36 @@ int get_clustername(const char **cluster)
static void dead_pcmk(int ci)
{
if (ci != pcmk_ci) {
- log_error("Unknown connection %d", ci);
+ log_printf(LOG_ERR, "Unknown connection %d", ci);
return;
}
- log_error("pacemaker connection died");
+ log_printf(LOG_ERR, "pacemaker connection died");
shutdown_daemon();
connection_dead(ci);
}
+extern void terminate_ais_connection(void);
+
void exit_stack(void)
{
- log_debug("closing stonithd connection");
- stonithd_signoff();
-
log_debug("closing pacemaker connection");
- if (ais_fd_async) {
- close(ais_fd_async);
- ais_fd_async = 0;
- }
- if (ais_fd_sync) {
- close(ais_fd_sync);
- ais_fd_sync = 0;
- }
+ terminate_ais_connection();
}
static void process_pcmk(int ci)
{
- /* ci ::= client number */
- char *data = NULL;
- char *uncompressed = NULL;
- AIS_Message *msg = NULL;
- SaAisErrorT rc = SA_AIS_OK;
- mar_res_header_t *header = NULL;
- static int header_len = sizeof(mar_res_header_t);
-
- header = malloc(header_len);
- memset(header, 0, header_len);
-
- errno = 0;
- rc = saRecvRetry(ais_fd_async, header, header_len);
- if (rc != SA_AIS_OK) {
- cl_perror("Receiving message header failed: (%d) %s", rc,
- ais_error2text(rc));
- goto bail;
- } else if(header->size == header_len) {
- log_error("Empty message: id=%d, size=%d, error=%d, header_len=%d",
- header->id, header->size, header->error, header_len);
- goto done;
- } else if(header->size == 0 || header->size < header_len) {
- log_error("Mangled header: size=%d, header=%d, error=%d",
- header->size, header_len, header->error);
- goto done;
- } else if(header->error != 0) {
- log_error("Header contined error: %d", header->error);
- }
-
- header = realloc(header, header->size);
- /* Use a char* so we can store the remainder into an offset */
- data = (char*)header;
-
- errno = 0;
- rc = saRecvRetry(ais_fd_async, data+header_len, header->size - header_len);
- msg = (AIS_Message*)data;
-
- if (rc != SA_AIS_OK) {
- cl_perror("Receiving message body failed: (%d) %s", rc, ais_error2text(rc));
- goto bail;
- }
-
- data = msg->data;
- if(msg->is_compressed && msg->size > 0) {
- int rc = BZ_OK;
- unsigned int new_size = msg->size;
-
- if (check_message_sanity(msg, NULL) == FALSE)
- goto badmsg;
-
- log_debug("Decompressing message data");
- uncompressed = malloc(new_size);
- memset(uncompressed, 0, new_size);
-
- rc = BZ2_bzBuffToBuffDecompress(
- uncompressed, &new_size, data, msg->compressed_size,
- 1, 0);
-
- if(rc != BZ_OK) {
- log_error("Decompression failed: %d", rc);
- goto badmsg;
- }
-
- CRM_ASSERT(rc == BZ_OK);
- CRM_ASSERT(new_size == msg->size);
-
- data = uncompressed;
-
- } else if(check_message_sanity(msg, data) == FALSE) {
- goto badmsg;
-
- } else if(safe_str_eq("identify", data)) {
- int pid = getpid();
- char *pid_s = crm_itoa(pid);
-
- send_ais_text(0, pid_s, TRUE, NULL, crm_msg_ais);
- crm_free(pid_s);
- goto done;
- }
-
- if (msg->header.id == crm_class_members) {
- xmlNode *xml = string2xml(data);
-
- if(xml != NULL) {
- const char *value = crm_element_value(xml, "id");
- if(value)
- crm_peer_seq = crm_int_helper(value, NULL);
-
- log_debug("Updating membership %llu", crm_peer_seq);
- /* crm_log_xml_info(xml, __PRETTY_FUNCTION__); */
- xml_child_iter(xml, node, crm_update_ais_node(node, crm_peer_seq));
- crm_calculate_quorum();
- free_xml(xml);
- } else {
- log_error("Invalid peer update: %s", data);
- }
- } else {
- log_error("Unexpected AIS message type: %d", msg->header.id);
- }
-
-done:
- free(uncompressed);
- free(msg);
- return;
-
-badmsg:
- log_error("Invalid message (id=%d, dest=%s:%s, from=%s:%s.%d):"
- " min=%d, total=%d, size=%d, bz2_size=%d",
- msg->id, ais_dest(&(msg->host)), msg_type2text(msg->host.type),
- ais_dest(&(msg->sender)), msg_type2text(msg->sender.type),
- msg->sender.pid, (int)sizeof(AIS_Message),
- msg->header.size, msg->size, msg->compressed_size);
- free(uncompressed);
- free(msg);
- return;
-
-bail:
- log_error("AIS connection failed");
- return;
-}
-
-static void dead_stonithd(int ci)
-{
- if (ci != stonithd_ci) {
- log_error("Unknown connection %d", ci);
- return;
- }
-
- log_error("stonithd connection died");
- shutdown_daemon();
- connection_dead(ci);
-}
-
-static void process_stonithd(int ci)
-{
- IPC_Channel *stonithd_ch = stonithd_input_IPC_channel();
-
- while (stonithd_op_result_ready()) {
- if (stonithd_ch->ch_status != IPC_CONNECT) {
- /* The message which was pending for us is that
- * the IPC status is now IPC_DISCONNECT */
- break;
- }
-
- if (ST_FAIL == stonithd_receive_ops_result(FALSE)) {
- log_error("stonithd_receive_ops_result() failed");
- }
- }
-
- if (stonithd_ch->ch_status != IPC_CONNECT)
- dead_stonithd(stonithd_ci);
-}
-
-static void result_stonithd(stonith_ops_t *op)
-{
- if (op == NULL) {
- log_error("Called with a NULL op!");
- return;
- }
-
- log_debug("Stonithd result: call=%d, optype=%d, node_name=%s, result=%d, node_list=%s, action=%s",
- op->call_id, op->optype, op->node_name, op->op_result,
- (char *)op->node_list, op->private_data);
-
- switch(op->op_result) {
- case STONITH_SUCCEEDED:
- break;
- case STONITH_CANNOT:
- case STONITH_TIMEOUT:
- case STONITH_GENERIC:
- log_error("Stonith of %s failed (%d)",
- op->node_name, op->op_result);
- break;
- default:
- log_error("Unsupported action result: %d", op->op_result);
- }
-}
-
-static gboolean setup_stonith(void)
-{
- int lpc = 0;
- int rc = ST_OK;
- int stonithd_fd;
- const char *reason = NULL;
- IPC_Channel *stonithd_ch = NULL;
-
- for(lpc = 0; lpc < 30; lpc++) {
- log_debug("Attempting connection to fencing daemon...");
-
- sleep(1);
- rc = stonithd_signon("ocfs2-tools");
- if(rc == ST_OK)
- break;
-
- log_error("Sign-in failed: pausing and trying again in 2s...");
- sleep(1);
- }
-
- if(rc != ST_OK) {
- reason = "Sign-in failed";
- goto bail;
- }
-
- rc = stonithd_set_stonith_ops_callback(result_stonithd);
- if(rc != ST_OK) {
- reason = "Setup failed";
- goto bail;
- }
-
- stonithd_ch = stonithd_input_IPC_channel();
- if(stonithd_ch == NULL) {
- reason = "No connection";
- goto bail;
- }
- stonithd_fd = stonithd_ch->ops->get_recv_select_fd(stonithd_ch);
- if(stonithd_ch <= 0) {
- reason = "No fd";
- goto bail;
- }
-
- stonithd_ci = connection_add(stonithd_fd, process_stonithd,
- dead_stonithd);
- if (stonithd_ci < 0) {
- log_error("Unable to add stonithd client: %s",
- strerror(-stonithd_ci));
- goto bail;
- }
-
- return TRUE;
-
-bail:
- log_error("Unable to add stonithd client: %s", reason);
- return FALSE;
+ ais_dispatch(ais_fd_async, NULL);
}
@@ -152,10 +154,10 @@ static void process_pcmk(int ci)
int setup_stack(void)
{
- int retries = 0;
- int pid;
- char *pid_s;
- int rc = SA_AIS_OK;
- struct utsname name;
-
crm_log_init("ocfs2_controld", LOG_INFO, FALSE, TRUE, 0, NULL);
- crm_peer_init();
- crm_log_init("ocfs2_controld", LOG_INFO, FALSE, TRUE, 0, NULL);
+ crm_log_init("ocfs2_controld", LOG_INFO, FALSE, TRUE, 0, NULL, FALSE);
- if (local_node_uname == NULL) {
- if (uname(&name) < 0) {
- cl_perror("uname(2) call failed");
- exit(100);
+ if(init_ais_connection(NULL, NULL, NULL, &local_node_uname, &our_nodeid) == FALSE) {
+ log_printf(LOG_ERR, "Connection to our AIS plugin (%d) failed", CRM_SERVICE);
+ return -1;
if(init_ais_connection(NULL, NULL, NULL, &local_node_uname, &our_nodeid) == FALSE) {
- log_error("Connection to our AIS plugin (%d) failed", CRM_SERVICE);
+ log_error("Connection to our AIS plugin (CRM) failed");
return -1;
}
- local_node_uname = crm_strdup(name.nodename);
- log_debug("Local node name: %s", local_node_uname);
- }
-
-retry:
- log_debug("Creating connection to our AIS plugin");
- rc = saServiceConnect (&ais_fd_sync, &ais_fd_async, CRM_SERVICE);
- if (rc != SA_AIS_OK)
- log_error("Connection to our AIS plugin (%d) failed: %s (%d)",
- CRM_SERVICE, ais_error2text(rc), rc);
-
- switch(rc) {
- case SA_AIS_OK:
- break;
- case SA_AIS_ERR_TRY_AGAIN:
- if(retries < 30) {
- sleep(1);
- retries++;
- goto retry;
- }
- log_error("Retry count exceeded");
- return 0;
- default:
- return 0;
- }
-
- log_debug("AIS connection established");
-
- pid = getpid();
- pid_s = crm_itoa(pid);
- send_ais_text(0, pid_s, TRUE, NULL, crm_msg_ais);
- crm_free(pid_s);
/* Sign up for membership updates */
send_ais_text(crm_class_notify, "true", TRUE, NULL, crm_msg_ais);
@@ -427,14 +186,11 @@ retry:
/* Requesting the current list of known nodes */
send_ais_text(crm_class_members, __FUNCTION__, TRUE, NULL, crm_msg_ais);
- our_nodeid = get_ais_nodeid();
- log_debug("Local node id: %d", our_nodeid);
-
pcmk_ci = connection_add(ais_fd_async, process_pcmk, dead_pcmk);
- if (pcmk_ci >= 0 && setup_stonith())
+ if (pcmk_ci >= 0)
return ais_fd_async;
- log_error("Unable to add pacemaker client: %s", strerror(-pcmk_ci));
+ log_printf(LOG_ERR, "Unable to add pacemaker client: %s", strerror(-pcmk_ci));
exit_stack();
return pcmk_ci;
}

View File

@ -1,22 +0,0 @@
From: lmb@suse.de
References: bnc#470741
ocfs2_controld.pcmk does not retry often enough for some situations, and
thus fails to start. This tentative patch "masks" this by simply
retrying much more often.
Index: ocfs2-tools/ocfs2_controld/ckpt.c
===================================================================
--- ocfs2-tools.orig/ocfs2_controld/ckpt.c
+++ ocfs2-tools/ocfs2_controld/ckpt.c
@@ -32,8 +32,8 @@
* A tentative retry is something we don't want to spend a lot of time on;
* it works or we error. A serious retry we really want to complete.
*/
-#define TENTATIVE_RETRY_TRIES 2
-#define SERIOUS_RETRY_TRIES 5
+#define TENTATIVE_RETRY_TRIES 20
+#define SERIOUS_RETRY_TRIES 50

View File

@ -1,41 +0,0 @@
From: Coly Li <coly.li@suse.de>
Subject: fix ocfs2console crashing when DISPLAY is not correctly set
References: bnc#448523
Author: Joel Becker <joel.becker@oracle.com>
When DISPLAY is not correctly set, this patch makes ocfs2console report error
mesage and exit, other than a ugly crash.
Signed-off-by: Joel Becker <joel.becker@oracle.com>
Signed-off-by: Coly Li <coly.li@suse.de>
---
diff --git a/ocfs2console/ocfs2console b/ocfs2console/ocfs2console
index 77ab623..17dcfc5 100755
--- a/ocfs2console/ocfs2console
+++ b/ocfs2console/ocfs2console
@@ -3,14 +3,23 @@
from ocfs2interface.about import process_args
nodeconf = process_args()
+import warnings
+warnings.filterwarnings("error")
+
try:
import gtk
-except RuntimeError:
+except Exception, e:
import sys
- print >>sys.stderr, '''ERROR: ocfs2console needs an X11 display.
+ if str(e).lower().find('display') == -1:
+ print >>sys.stderr, '''ERROR: Unable to initialize the windowing
+system: %s\n''' % e
+ else:
+ print >>sys.stderr, '''ERROR: ocfs2console needs an X11 display.
Make sure a proper setup for your display environment exists.\n'''
sys.exit(1)
+warnings.resetwarnings()
+
if nodeconf:
from ocfs2interface.nodeconfig import node_config
node_config()

View File

@ -1,29 +0,0 @@
From: Coly Li <coly.li@suse.de>
Subject: ocfs2console: remove unsupported option when calling tunefs.ocfs2
References: bnc#472353
commit 1adbec9a9d409f3f2c127ddbff8c4504e2d126ed
Author: Coly Li <coly.li@suse.de>
Date: Sun Feb 8 12:20:05 2009 +0800
ocfs2console: remove unsupported option when calling tunefs.ocfs2
ocfs2interface/tune.py call tunefs.ocfs2 with -x option, which is not supported in tunefs.ocfs2.
This patch remove this unsupported option from ocfs2console.
Signed-off-by: Coly Li <coly.li@suse.de>
Cc: Joel Becker <joel.becker@oracle.com>
Signed-off-by: Joel Becker <joel.becker@oracle.com>
diff --git a/ocfs2console/ocfs2interface/tune.py b/ocfs2console/ocfs2interface/tune.py
index c76dbaa..0e514bd 100644
--- a/ocfs2console/ocfs2interface/tune.py
+++ b/ocfs2console/ocfs2interface/tune.py
@@ -24,7 +24,7 @@ from process import Process
from fswidgets import NumSlots, VolumeLabel
-base_command = ('tunefs.ocfs2', '-x')
+base_command = ('tunefs.ocfs2',)
class TuneVolumeLabel(VolumeLabel):
def __init__(self, device=None):

View File

@ -1,33 +0,0 @@
From: Coly Li <coly.li@suse.de>
Subject: ocfs2console: Whoops, don't reset all warnings, just pop the DISPLAY one
References: bnc#448523
Author: Hu Ziming <huzim@cn.ibm.com>
comment from patch by Joel:
We turn warnings into error while calling 'import gtk' to handle a pygtk
bug with an invalid DISPLAY. After we return from 'import gtk', we were
calling warnings.resetwarnings() to get back to the normal state.
However, it looks like that clears more warning filters than the one we
added. Let's fix this.
comment from bugzilla by Joel:
Ziming Hu's patch for fixing the warning filters is now upstream. I regret to
say that since I hand-coded it from memory, I forgot to credit him with the
discovery before committing. That credit will live here.
Signed-off-by: Hu Ziming <huzim@cn.ibm.com>
Signed-off-by: Joel Becker <joel.becker@oracle.com>
Signed-off-by: Coly Li <coly.li@suse.de>
---
diff -ru ocfs2-tools/ocfs2console/ocfs2console ocfs2-tools-new/ocfs2console/ocfs2console
--- ocfs2-tools/ocfs2console/ocfs2console 2009-02-17 06:06:57.910766000 +0100
+++ ocfs2-tools-new/ocfs2console/ocfs2console 2009-02-17 06:09:32.935591000 +0100
@@ -17,8 +17,7 @@
print >>sys.stderr, '''ERROR: ocfs2console needs an X11 display.
Make sure a proper setup for your display environment exists.\n'''
sys.exit(1)
-
-warnings.resetwarnings()
+warnings.filters.pop(0)
if nodeconf:
from ocfs2interface.nodeconfig import node_config

57
reflink-no-syscall.patch Normal file
View File

@ -0,0 +1,57 @@
Index: reflink/coreutils-6.9/src/ln.c
===================================================================
--- reflink.orig/coreutils-6.9/src/ln.c
+++ reflink/coreutils-6.9/src/ln.c
@@ -152,52 +152,6 @@ target_directory_operand (char const *fi
return is_a_dir;
}
-#ifndef HAVE_REFLINK
-# ifndef HAVE_REFLINKAT
-# include <sys/syscall.h>
-
-# ifndef SYS_reflinkat
-# ifdef __i386__
-# define __NR_reflinkat 337
-# endif
-# ifdef __x86_64__
-# define __NR_reflinkat 299
-# endif
-# define SYS_reflinkat __NR_reflinkat
-# endif /* SYS_reflinkat */
-
-# ifdef SYS_reflinkat
-static int reflinkat(int olddirfd, const char *oldpath,
- int newdirfd, const char *newpath,
- int preserve, int flags)
-{
- return syscall(SYS_reflinkat, olddirfd, oldpath, newdirfd, newpath,
- preserve, flags);
-}
-# else
-static int reflinkat(int olddirfd, const char *oldpath,
- int newdirfd, const char *newpath,
- int preserve, int flags)
-{
- return -ENOSYS;
-}
-# endif /* SYS_reflinkat */
-# endif /* HAVE_REFLINKAT */
-
-/*
- * We've now defined reflinkat of some sort. We can use it to build
- * reflink.
- */
-# ifndef AT_FDCWD
-# define AT_FDCWD -100
-# endif
-static int reflink(const char *oldpath, const char *newpath,
- int preserve)
-{
- return reflinkat(AT_FDCWD, oldpath, AT_FDCWD, newpath, preserve, 0);
-}
-#endif /* HAVE_REFLINK */
-
#ifndef REFLINK_ATTR_NONE
# define REFLINK_ATTR_NONE 0
#endif

3
reflink.tar.bz2 Normal file
View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d197e3c716ab12213332d9787375fecda0ede55508ca1e71aec9922e8c124ba5
size 5167807

View File

@ -1,43 +0,0 @@
commit f5939cb6da32352a782e36507b5bef8a8194b26d
Author: Coly Li <coly.li@suse.de>
Date: Tue Feb 24 09:43:04 2009 +0800
tunefs.ocfs2.8: add info for -y,-n,--update-cluster-stack
The manual for tunefs.ocfs2.8.in does not have information for -y, -n and
--update-cluster-stack options. This patch adds these info to tuneofs.ocfs2
manual.
Signed-off-by: Coly Li <coly.li@suse.de>
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
diff --git a/tunefs.ocfs2/tunefs.ocfs2.8.in b/tunefs.ocfs2/tunefs.ocfs2.8.in
index 7a9b66b..b49a00f 100644
--- a/tunefs.ocfs2/tunefs.ocfs2.8.in
+++ b/tunefs.ocfs2/tunefs.ocfs2.8.in
@@ -90,6 +90,14 @@ Verbose mode.
Show version and exit.
.TP
+\fB\-y, \-\-yes\fR
+Alway answer Yes in interactive command line.
+
+.TP
+\fB\-n, \-\-no\fR
+Always answer No in interactive command line.
+
+.TP
\fB\-\-backup\-super\fR
Backs up the superblock to fixed offsets (1G, 4G, 16G, 64G, 256G and 1T)
on disk. This option is useful for users to backup the superblock on volumes
@@ -102,6 +110,10 @@ facility.
Lists the files having holes. This option is useful when disabling the \fIsparse\fR feature.
.TP
+\fB\-\-update-cluster-stack\fR
+Updating on-disk cluster information to match the running cluster.
+
+.TP
\fIblocks-count\fR
During resize, \fBtunefs.ocfs2\fR automatically determines the size of the given
device and grows the file system such that it uses all of the available space on

18
version-1.4.3.patch Normal file
View File

@ -0,0 +1,18 @@
This patch keeps ocfs2-tools version as 1.4.3, until we decide to update the package version.
Signed-off-by: Coly Li <coly.li@suse.de>
---
diff -ur ocfs2-tools/configure.in ocfs2-tools-new//configure.in
--- ocfs2-tools/configure.in 2010-02-20 01:21:46.000000000 +0800
+++ ocfs2-tools-new//configure.in 2010-03-11 09:38:01.000000000 +0800
@@ -8,8 +8,8 @@
# Adjust these for the software version.
MAJOR_VERSION=1
-MINOR_VERSION=6
-MICRO_VERSION=0
+MINOR_VERSION=4
+MICRO_VERSION=3
EXTRA_VERSION=
DIST_VERSION=$MAJOR_VERSION.$MINOR_VERSION.$MICRO_VERSION