From 24b059e1e75a0ff5dabb8a6dfdc09e82d488c244 Mon Sep 17 00:00:00 2001 From: Coly Li 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 Cc: Mark Fasheh Cc: Tao Ma --- 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