diff options
author | Theodore Ts'o <tytso@mit.edu> | 2007-09-23 11:39:24 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2007-09-23 11:39:24 -0400 |
commit | f6341e9c70eb4e0ded51ca96aeaa79a72222c069 (patch) | |
tree | 36c8877202a9291bdbbae7426c71251459e878e8 | |
parent | 846be6db813895c354cc54beaa8fa6aba8d98085 (diff) | |
download | e2fsprogs-f6341e9c70eb4e0ded51ca96aeaa79a72222c069.tar.gz |
ext2fs_dblist_dir_iterate: Fix ABORT propagation logic
ext2fs_dblist_dir_iterate() calls ext2fs_dblist_iterate(), which calls
ext2fs_process_dir_block(), which in turn calls the helper function
db_dir_proc() which calls callback function passed into
ext2fs_dblist_dir_iterate(). At each stage the conventions for
signalling requests to abort the iteration or to signal errors
changes, db_dir_proc() was not properly mapping the abort request back
to ext2fs_dblist_iterate().
Currently db_dir_proc() is ignoring errors (i/o errors or directory
block corrupt errors) from ext2fs_process_dir_block(), since the main
user of ext2fs_dblist_dir_iterate() is e2fsck, for which this is the
correct behavior. In the future ext2fs_dblist_dir_iterate() could
take a flag which would cause it to abort if
ext2fs_process_dir_block() returns an error; however, it's not clear
how useful this would be since we don't have a way of signalling the
exact nature of which block had the error, and the caller wouldn't
have a good way of knowing what percentage of the directory block list
had been processed. Ultimately this may not be the best interface for
applications that need that level of error reporting.
Thanks to Vladimir V. Saveliev <vs@clusterfs.com> for pointing out
this problem.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
-rw-r--r-- | lib/ext2fs/dblist_dir.c | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/lib/ext2fs/dblist_dir.c b/lib/ext2fs/dblist_dir.c index f2e17a61..28a04c74 100644 --- a/lib/ext2fs/dblist_dir.c +++ b/lib/ext2fs/dblist_dir.c @@ -66,10 +66,15 @@ static int db_dir_proc(ext2_filsys fs, struct ext2_db_entry *db_info, void *priv_data) { struct dir_context *ctx; + int ret; ctx = (struct dir_context *) priv_data; ctx->dir = db_info->ino; + ctx->errcode = 0; - return ext2fs_process_dir_block(fs, &db_info->blk, - db_info->blockcnt, 0, 0, priv_data); + ret = ext2fs_process_dir_block(fs, &db_info->blk, + db_info->blockcnt, 0, 0, priv_data); + if ((ret & BLOCK_ABORT) && !ctx->errcode) + return DBLIST_ABORT; + return 0; } |