[Ocfs2-devel] [PATCH 3/3] Disable index directory in case of an error
Goldwyn Rodrigues
rgoldwyn at gmail.com
Wed Aug 3 15:49:44 PDT 2011
The first encounter with index directory is while performing
ocfs2_find_entry(). An error here disables the index directory in
ocfs2_inode_info only.
If this is a write/modify operation, this is later picked up
ocfs2_delete_entry or ocfs2_prepare_dir_for_insert and disabled in the
disk structures as well.
This means a simple "ls" operation only disables in the inode_info,
which is fine. If there is an operation not covered, let me know.
Signed-off-by: Goldwyn Rodrigues <rgoldwyn at suse.de>
---
fs/ocfs2/dir.c | 32 +++++++++++++++++++++++++++++---
fs/ocfs2/dir.h | 2 +-
fs/ocfs2/namei.c | 8 +++++---
3 files changed, 35 insertions(+), 7 deletions(-)
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c
index 94061ab..cbae077 100644
--- a/fs/ocfs2/dir.c
+++ b/fs/ocfs2/dir.c
@@ -1102,9 +1102,15 @@ int ocfs2_find_entry(const char *name, int namelen,
{
struct buffer_head *bh;
struct ocfs2_dir_entry *res_dir = NULL;
+ int ret;
- if (ocfs2_dir_indexed(dir))
- return ocfs2_find_entry_dx(name, namelen, dir, lookup);
+ if (ocfs2_dir_indexed(dir)) {
+ ret = ocfs2_find_entry_dx(name, namelen, dir, lookup);
+ if (ret == -EIO)
+ ocfs2_dx_dir_disable(dir);
+ else
+ return ret;
+ }
/*
* The unindexed dir code only uses part of the lookup
@@ -1427,12 +1433,23 @@ static inline int
ocfs2_delete_entry_el(handle_t *handle,
* implementation from the caller.
*/
int ocfs2_delete_entry(handle_t *handle,
- struct inode *dir,
+ struct inode *dir, struct buffer_head *di_bh,
struct ocfs2_dir_lookup_result *res)
{
+ struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
if (ocfs2_dir_indexed(dir))
return ocfs2_delete_entry_dx(handle, dir, res);
+ /* Clear Index directory references in case of dx errors during
+ * ocfs2_find_entry()
+ */
+ if (ocfs2_supports_indexed_dirs(osb) && !ocfs2_dir_indexed(dir)) {
+ struct ocfs2_dinode *di =
+ (struct ocfs2_dinode *)di_bh->b_data;
+ di->i_dyn_features = cpu_to_le16(OCFS2_I(dir)->ip_dyn_features);
+ di->i_dx_root = cpu_to_le64(0ULL);
+ }
+
if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL)
return ocfs2_delete_entry_id(handle, dir, res->dl_entry,
res->dl_leaf_bh);
@@ -4381,6 +4398,15 @@ int ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb,
mlog_errno(ret);
goto out;
}
+ /* Clear Index directory references in case of dx errors during
+ * ocfs2_find_entry()
+ */
+ if (ocfs2_supports_indexed_dirs(osb) && !ocfs2_dir_indexed(dir)) {
+ struct ocfs2_dinode *di =
+ (struct ocfs2_dinode *)parent_fe_bh->b_data;
+ di->i_dyn_features = cpu_to_le16(OCFS2_I(dir)->ip_dyn_features);
+ di->i_dx_root = cpu_to_le64(0ULL);
+ }
if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL) {
ret = ocfs2_find_dir_space_id(dir, parent_fe_bh, name,
diff --git a/fs/ocfs2/dir.h b/fs/ocfs2/dir.h
index e683f3d..9dd8e8a 100644
--- a/fs/ocfs2/dir.h
+++ b/fs/ocfs2/dir.h
@@ -58,7 +58,7 @@ int ocfs2_find_entry(const char *name, int namelen,
struct inode *dir,
struct ocfs2_dir_lookup_result *lookup);
int ocfs2_delete_entry(handle_t *handle,
- struct inode *dir,
+ struct inode *dir, struct buffer_head *di_bh,
struct ocfs2_dir_lookup_result *res);
int __ocfs2_add_entry(handle_t *handle,
struct inode *dir,
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index 53aa41e..e14d05c 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -904,7 +904,7 @@ static int ocfs2_unlink(struct inode *dir,
}
/* delete the name from the parent dir */
- status = ocfs2_delete_entry(handle, dir, &lookup);
+ status = ocfs2_delete_entry(handle, dir, parent_node_bh, &lookup);
if (status < 0) {
mlog_errno(status);
goto leave;
@@ -1372,7 +1372,8 @@ static int ocfs2_rename(struct inode *old_dir,
if (status)
goto bail;
- status = ocfs2_delete_entry(handle, old_dir, &old_entry_lookup);
+ status = ocfs2_delete_entry(handle, old_dir, old_dir_bh,
+ &old_entry_lookup);
if (status < 0) {
mlog_errno(status);
goto bail;
@@ -2097,7 +2098,8 @@ int ocfs2_orphan_del(struct ocfs2_super *osb,
}
/* remove it from the orphan directory */
- status = ocfs2_delete_entry(handle, orphan_dir_inode, &lookup);
+ status = ocfs2_delete_entry(handle, orphan_dir_inode, orphan_dir_bh,
+ &lookup);
if (status < 0) {
mlog_errno(status);
goto leave;
--
1.7.6
More information about the Ocfs2-devel
mailing list