[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20071011191654.4599.28529.stgit@gara>
Date: Thu, 11 Oct 2007 14:16:54 -0500
From: "Jose R. Santos" <jrs@...ibm.com>
To: linux-ext4@...r.kernel.org
Subject: [PATCH 09/13][e2fsprogs] Make e2fsck uninit block group aware.
From: Jose R. Santos <jrs@...ibm.com>
Make e2fsck uninit block group aware.
This patch has all the necesary pieces to open and fix filesystems created
with the uninit block group feature.
Signed-off-by: Jose R. Santos <jrs@...ibm.com>
--
e2fsck/e2fsck.h | 2 +
e2fsck/journal.c | 2 +
e2fsck/pass2.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++------
e2fsck/pass5.c | 61 +++++++++++++++++++++++++++++++------------
e2fsck/problem.c | 42 +++++++++++++++++++++++++++++
e2fsck/problem.h | 26 ++++++++++++++++++
e2fsck/super.c | 40 ++++++++++++++++++++++++++++
e2fsck/unix.c | 11 ++++++--
e2fsck/util.c | 61 +++++++++++++++++++++++++++++++++++++++++++
9 files changed, 292 insertions(+), 30 deletions(-)
diff --git a/e2fsck/e2fsck.h b/e2fsck/e2fsck.h
index 9ccffd8..a67322d 100644
--- a/e2fsck/e2fsck.h
+++ b/e2fsck/e2fsck.h
@@ -468,6 +468,8 @@ extern void e2fsck_read_bitmaps(e2fsck_t ctx);
extern void e2fsck_write_bitmaps(e2fsck_t ctx);
extern void preenhalt(e2fsck_t ctx);
extern char *string_copy(e2fsck_t ctx, const char *str, int len);
+extern errcode_t e2fsck_zero_blocks(ext2_filsys fs, blk_t blk, int num,
+ blk_t *ret_blk, int *ret_count);
#ifdef RESOURCE_TRACK
extern void print_resource_track(const char *desc,
struct resource_track *track,
diff --git a/e2fsck/journal.c b/e2fsck/journal.c
index f5f4647..ceade93 100644
--- a/e2fsck/journal.c
+++ b/e2fsck/journal.c
@@ -988,6 +988,8 @@ void e2fsck_move_ext3_journal(e2fsck_t ctx)
ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
ext2fs_mark_ib_dirty(fs);
fs->group_desc[group].bg_free_inodes_count++;
+ fs->group_desc[group].bg_checksum =
+ ext2fs_group_desc_csum(fs->super, group,&fs->group_desc[group]);
fs->super->s_free_inodes_count++;
return;
diff --git a/e2fsck/pass2.c b/e2fsck/pass2.c
index 27f7136..047b5ca 100644
--- a/e2fsck/pass2.c
+++ b/e2fsck/pass2.c
@@ -151,7 +151,7 @@ void e2fsck_pass2(e2fsck_t ctx)
cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block,
&cd);
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+ if (ctx->flags & E2F_FLAG_SIGNAL_MASK || ctx->flags & E2F_FLAG_RESTART)
return;
if (cd.pctx.errcode) {
fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
@@ -736,7 +736,7 @@ static int check_dir_block(ext2_filsys fs,
buf = cd->buf;
ctx = cd->ctx;
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+ if (ctx->flags & E2F_FLAG_SIGNAL_MASK || ctx->flags & E2F_FLAG_RESTART)
return DIRENT_ABORT;
if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
@@ -833,6 +833,9 @@ static int check_dir_block(ext2_filsys fs,
dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
prev = 0;
do {
+ int group;
+ ext2_ino_t first_unused_inode;
+
problem = 0;
dirent = (struct ext2_dir_entry *) (buf + offset);
cd->pctx.dirent = dirent;
@@ -882,12 +885,6 @@ static int check_dir_block(ext2_filsys fs,
(dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
(dirent->inode > fs->super->s_inodes_count)) {
problem = PR_2_BAD_INO;
- } else if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map,
- dirent->inode))) {
- /*
- * If the inode is unused, offer to clear it.
- */
- problem = PR_2_UNUSED_INODE;
} else if (ctx->inode_bb_map &&
(ext2fs_test_inode_bitmap(ctx->inode_bb_map,
dirent->inode))) {
@@ -964,6 +961,67 @@ static int check_dir_block(ext2_filsys fs,
return DIRENT_ABORT;
}
+ group = ext2fs_group_of_ino(fs, dirent->inode);
+ first_unused_inode = group * fs->super->s_inodes_per_group +
+ 1 + fs->super->s_inodes_per_group -
+ fs->group_desc[group].bg_itable_unused;
+ cd->pctx.group = group;
+
+ /*
+ * Check if the inode was missed out because _INODE_UNINIT
+ * flag was set or bg_itable_unused was incorrect.
+ * If that is the case restart e2fsck.
+ * XXX Optimisations TODO:
+ * 1. only restart e2fsck once
+ * 2. only exposed inodes are checked again.
+ */
+ if (fs->group_desc[group].bg_flags & EXT2_BG_INODE_UNINIT) {
+ if (fix_problem(ctx, PR_2_INOREF_BG_INO_UNINIT,
+ &cd->pctx)){
+ fs->group_desc[group].bg_flags &=
+ ~EXT2_BG_INODE_UNINIT;
+ ctx->flags |= E2F_FLAG_RESTART |
+ E2F_FLAG_SIGNAL_MASK;
+ } else {
+ ext2fs_unmark_valid(fs);
+ if (problem == PR_2_BAD_INO)
+ goto next;
+ }
+ } else if (dirent->inode >= first_unused_inode) {
+ if (fix_problem(ctx, PR_2_INOREF_IN_UNUSED, &cd->pctx)){
+ fs->group_desc[group].bg_itable_unused = 0;
+ fs->group_desc[group].bg_flags &=
+ ~EXT2_BG_INODE_UNINIT;
+ ext2fs_mark_super_dirty(fs);
+ ctx->flags |= E2F_FLAG_RESTART;
+ goto restart_fsck;
+ } else {
+ ext2fs_unmark_valid(fs);
+ if (problem == PR_2_BAD_INO)
+ goto next;
+ }
+ }
+
+ if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map,
+ dirent->inode))) {
+ /*
+ * If the inode is unused, offer to clear it.
+ */
+ problem = PR_2_UNUSED_INODE;
+ }
+
+ if (problem) {
+ if (fix_problem(ctx, problem, &cd->pctx)) {
+ dirent->inode = 0;
+ dir_modified++;
+ goto next;
+ } else {
+ ext2fs_unmark_valid(fs);
+ if (problem == PR_2_BAD_INO)
+ goto next;
+ }
+ }
+
if (check_name(ctx, dirent, ino, &cd->pctx))
dir_modified++;
@@ -1073,8 +1131,9 @@ static int check_dir_block(ext2_filsys fs,
dict_free_nodes(&de_dict);
return 0;
abort_free_dict:
- dict_free_nodes(&de_dict);
ctx->flags |= E2F_FLAG_ABORT;
+restart_fsck:
+ dict_free_nodes(&de_dict);
return DIRENT_ABORT;
}
diff --git a/e2fsck/pass5.c b/e2fsck/pass5.c
index 53248b0..1f1536b 100644
--- a/e2fsck/pass5.c
+++ b/e2fsck/pass5.c
@@ -121,7 +121,7 @@ static void check_block_bitmaps(e2fsck_t ctx)
struct problem_context pctx;
int problem, save_problem, fixit, had_problem;
errcode_t retval;
- int lazy_bg = 0;
+ int lazy_flag, csum_flag;
int skip_group = 0;
clear_problem_context(&pctx);
@@ -158,15 +158,16 @@ static void check_block_bitmaps(e2fsck_t ctx)
goto errout;
}
- if (EXT2_HAS_COMPAT_FEATURE(fs->super, EXT2_FEATURE_COMPAT_LAZY_BG))
- lazy_bg++;
-
+ lazy_flag = EXT2_HAS_COMPAT_FEATURE(fs->super,
+ EXT2_FEATURE_COMPAT_LAZY_BG);
+ csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
redo_counts:
had_problem = 0;
save_problem = 0;
pctx.blk = pctx.blk2 = NO_BLK;
- if (lazy_bg && (fs->group_desc[group].bg_flags &
- EXT2_BG_BLOCK_UNINIT))
+ if ((lazy_flag || csum_flag) &&
+ (fs->group_desc[group].bg_flags & EXT2_BG_BLOCK_UNINIT))
skip_group++;
super = fs->super->s_first_data_block;
for (i = fs->super->s_first_data_block;
@@ -206,6 +207,17 @@ redo_counts:
* Block used, but not marked in use in the bitmap.
*/
problem = PR_5_BLOCK_USED;
+
+ if (skip_group) {
+ struct problem_context pctx2;
+ pctx2.blk = i;
+ pctx2.group = group;
+ if (fix_problem(ctx, PR_5_BLOCK_UNINIT,&pctx2)){
+ fs->group_desc[group].bg_flags &=
+ ~EXT2_BG_BLOCK_UNINIT;
+ skip_group = 0;
+ }
+ }
}
if (pctx.blk == NO_BLK) {
pctx.blk = pctx.blk2 = i;
@@ -224,7 +236,7 @@ redo_counts:
had_problem++;
do_counts:
- if (!bitmap && !skip_group) {
+ if (!bitmap && (!skip_group || csum_flag)) {
group_free++;
free_blocks++;
}
@@ -241,7 +253,7 @@ redo_counts:
if ((ctx->progress)(ctx, 5, group,
fs->group_desc_count*2))
goto errout;
- if (lazy_bg &&
+ if ((lazy_flag || csum_flag) &&
(i != fs->super->s_blocks_count-1) &&
(fs->group_desc[group].bg_flags &
EXT2_BG_BLOCK_UNINIT))
@@ -321,7 +333,7 @@ static void check_inode_bitmaps(e2fsck_t ctx)
errcode_t retval;
struct problem_context pctx;
int problem, save_problem, fixit, had_problem;
- int lazy_bg = 0;
+ int lazy_flag, csum_flag;
int skip_group = 0;
clear_problem_context(&pctx);
@@ -358,16 +370,16 @@ static void check_inode_bitmaps(e2fsck_t ctx)
goto errout;
}
- if (EXT2_HAS_COMPAT_FEATURE(fs->super,
- EXT2_FEATURE_COMPAT_LAZY_BG))
- lazy_bg++;
-
+ lazy_flag = EXT2_HAS_COMPAT_FEATURE(fs->super,
+ EXT2_FEATURE_COMPAT_LAZY_BG);
+ csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
redo_counts:
had_problem = 0;
save_problem = 0;
pctx.ino = pctx.ino2 = 0;
- if (lazy_bg && (fs->group_desc[group].bg_flags &
- EXT2_BG_INODE_UNINIT))
+ if ((lazy_flag || csum_flag) &&
+ (fs->group_desc[group].bg_flags & EXT2_BG_INODE_UNINIT))
skip_group++;
/* Protect loop from wrap-around if inodes_count is maxed */
@@ -390,6 +402,21 @@ redo_counts:
* Inode used, but not in bitmap
*/
problem = PR_5_INODE_USED;
+
+ /* We should never hit this, because it means that
+ * inodes were marked in use that weren't noticed
+ * in pass1 or pass 2. It is easier to fix the problem
+ * than to kill e2fsck and leave the user stuck. */
+ if (skip_group) {
+ struct problem_context pctx2;
+ pctx2.blk = i;
+ pctx2.group = group;
+ if (fix_problem(ctx, PR_5_INODE_UNINIT,&pctx2)){
+ fs->group_desc[group].bg_flags &=
+ ~EXT2_BG_INODE_UNINIT;
+ skip_group = 0;
+ }
+ }
}
if (pctx.ino == 0) {
pctx.ino = pctx.ino2 = i;
@@ -411,7 +438,7 @@ do_counts:
if (bitmap) {
if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
dirs_count++;
- } else if (!skip_group) {
+ } else if (!skip_group || csum_flag) {
group_free++;
free_inodes++;
}
@@ -430,7 +457,7 @@ do_counts:
group + fs->group_desc_count,
fs->group_desc_count*2))
goto errout;
- if (lazy_bg &&
+ if ((lazy_flag || csum_flag) &&
(i != fs->super->s_inodes_count) &&
(fs->group_desc[group].bg_flags &
EXT2_BG_INODE_UNINIT))
diff --git a/e2fsck/problem.c b/e2fsck/problem.c
index 7c3ebea..6fc811c 100644
--- a/e2fsck/problem.c
+++ b/e2fsck/problem.c
@@ -351,8 +351,28 @@ static struct e2fsck_problem problem_table[] = {
N_("Adding dirhash hint to @f.\n\n"),
PROMPT_NONE, 0 },
+ /* group descriptor N checksum is invalid. */
+ { PR_0_GDT_CSUM,
+ N_("@g descriptor %g checksum is invalid. "),
+ PROMPT_FIX, PR_PREEN_OK },
+
+ /* group descriptor N marked uninitialized without feature set. */
+ { PR_0_GDT_UNINIT,
+ N_("@g descriptor %g marked uninitialized without feature set.\n"),
+ PROMPT_FIX, PR_PREEN_OK },
+
+ /* group N block bitmap uninitialized but inode bitmap in use. */
+ { PR_0_BB_UNINIT_IB_INIT,
+ N_("@g %g @b @B uninitialized but @i @B in use.\n"),
+ PROMPT_FIX, PR_PREEN_OK },
+
+ /* Group descriptor N has invalid unused inodes count. */
+ { PR_0_GDT_ITABLE_UNUSED,
+ N_("@g descriptor %g has invalid unused inodes count %b. "),
+ PROMPT_FIX, PR_PREEN_OK },
+
/* Pass 1 errors */
-
+
/* Pass 1: Checking inodes, blocks, and sizes */
{ PR_1_PASS_HEADER,
N_("Pass 1: Checking @is, @bs, and sizes\n"),
@@ -1188,6 +1208,16 @@ static struct e2fsck_problem problem_table[] = {
N_("i_blocks_hi @F %N, @s zero.\n"),
PROMPT_CLEAR, 0 },
+ /* Inode found in group where _INODE_UNINIT is set */
+ { PR_2_INOREF_BG_INO_UNINIT,
+ N_("@i %i found in @g %g where _INODE_UNINIT is set. "),
+ PROMPT_FIX, PR_PREEN_OK },
+
+ /* Inode found in group unused inodes area */
+ { PR_2_INOREF_IN_UNUSED,
+ N_("@i %i found in @g %g unused inodes area. "),
+ PROMPT_FIX, PR_PREEN_OK },
+
/* Pass 3 errors */
/* Pass 3: Checking directory connectivity */
@@ -1499,6 +1529,16 @@ static struct e2fsck_problem problem_table[] = {
N_("Recreate journal to make the filesystem ext3 again?\n"),
PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
+ /* Group N block(s) in use but group is marked BLOCK_UNINIT */
+ { PR_5_BLOCK_UNINIT,
+ N_("@g %g @b(s) in use but @g is marked BLOCK_UNINIT\n"),
+ PROMPT_FIX, PR_PREEN_OK },
+
+ /* Group N inode(s) in use but group is marked INODE_UNINIT */
+ { PR_5_INODE_UNINIT,
+ N_("@g %g @i(s) in use but @g is marked INODE_UNINIT\n"),
+ PROMPT_FIX, PR_PREEN_OK },
+
{ 0 }
};
diff --git a/e2fsck/problem.h b/e2fsck/problem.h
index f5f7212..8ec9ee5 100644
--- a/e2fsck/problem.h
+++ b/e2fsck/problem.h
@@ -196,6 +196,18 @@ struct problem_context {
/* Superblock hint for external journal incorrect */
#define PR_0_DIRHASH_HINT 0x000034
+/* Group descriptor N checksum is invalid */
+#define PR_0_GDT_CSUM 0x000035
+
+/* Group descriptor N marked uninitialized without feature set. */
+#define PR_0_GDT_UNINIT 0x000036
+
+/* Block bitmap is not initialised and Inode bitmap is */
+#define PR_0_BB_UNINIT_IB_INIT 0x000037
+
+/* Group descriptor N has invalid unused inodes count. */
+#define PR_0_GDT_ITABLE_UNUSED 0x000038
+
/*
* Pass 1 errors
*/
@@ -708,6 +720,12 @@ struct problem_context {
/* i_blocks_hi should be zero */
#define PR_2_BLOCKS_HI_ZERO 0x020044
+/* Inode found in group where _INODE_UNINIT is set */
+#define PR_2_INOREF_BG_INO_UNINIT 0x020045
+
+/* Inode found in group unused inodes area */
+#define PR_2_INOREF_IN_UNUSED 0x020046
+
/*
* Pass 3 errors
*/
@@ -896,10 +914,16 @@ struct problem_context {
/* Inode range not used, but marked in bitmap */
#define PR_5_INODE_RANGE_UNUSED 0x050016
-
+
/* Inode rangeused, but not marked used in bitmap */
#define PR_5_INODE_RANGE_USED 0x050017
+/* Block in use but group is marked BLOCK_UNINIT */
+#define PR_5_BLOCK_UNINIT 0x050018
+
+/* Inode in use but group is marked INODE_UNINIT */
+#define PR_5_INODE_UNINIT 0x050019
+
/*
* Post-Pass 5 errors
*/
diff --git a/e2fsck/super.c b/e2fsck/super.c
index a4835f7..6b39a65 100644
--- a/e2fsck/super.c
+++ b/e2fsck/super.c
@@ -468,6 +468,7 @@ void check_super_block(e2fsck_t ctx)
blk_t should_be;
struct problem_context pctx;
__u32 free_blocks = 0, free_inodes = 0;
+ int lazy_flag, csum_flag;
inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super);
ipg_max = inodes_per_block * (blocks_per_group - 4);
@@ -576,6 +577,10 @@ void check_super_block(e2fsck_t ctx)
*/
first_block = sb->s_first_data_block;
+ lazy_flag = EXT2_HAS_COMPAT_FEATURE(fs->super,
+ EXT2_FEATURE_COMPAT_LAZY_BG);
+ csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) {
pctx.group = i;
@@ -621,6 +626,41 @@ void check_super_block(e2fsck_t ctx)
(gd->bg_used_dirs_count > sb->s_inodes_per_group))
ext2fs_unmark_valid(fs);
+ if (!ext2fs_group_desc_csum_verify(sb, i, gd)) {
+ if (fix_problem(ctx, PR_0_GDT_CSUM, &pctx)) {
+ gd->bg_flags &= ~(EXT2_BG_BLOCK_UNINIT |
+ EXT2_BG_INODE_UNINIT);
+ gd->bg_itable_unused = 0;
+ }
+ ext2fs_unmark_valid(fs);
+ }
+
+ if (!lazy_flag && !csum_flag &&
+ (gd->bg_flags &(EXT2_BG_BLOCK_UNINIT|EXT2_BG_INODE_UNINIT)||
+ gd->bg_itable_unused != 0)){
+ if (fix_problem(ctx, PR_0_GDT_UNINIT, &pctx)) {
+ gd->bg_flags &= ~(EXT2_BG_BLOCK_UNINIT |
+ EXT2_BG_INODE_UNINIT);
+ gd->bg_itable_unused = 0;
+ }
+ ext2fs_unmark_valid(fs);
+ }
+ if (gd->bg_flags & EXT2_BG_BLOCK_UNINIT &&
+ !(gd->bg_flags & EXT2_BG_INODE_UNINIT)) {
+ if (fix_problem(ctx, PR_0_BB_UNINIT_IB_INIT, &pctx))
+ gd->bg_flags &= ~EXT2_BG_BLOCK_UNINIT;
+ ext2fs_unmark_valid(fs);
+ }
+ if (csum_flag &&
+ (gd->bg_itable_unused > gd->bg_free_inodes_count ||
+ gd->bg_itable_unused > sb->s_inodes_per_group)) {
+ pctx.blk = gd->bg_itable_unused;
+ if (fix_problem(ctx, PR_0_GDT_ITABLE_UNUSED, &pctx))
+ gd->bg_itable_unused = 0;
+ ext2fs_unmark_valid(fs);
+ }
+
+ gd->bg_checksum = ext2fs_group_desc_csum(fs->super, i, gd);
}
/*
diff --git a/e2fsck/unix.c b/e2fsck/unix.c
index 291ff85..596c650 100644
--- a/e2fsck/unix.c
+++ b/e2fsck/unix.c
@@ -558,7 +558,9 @@ static void parse_extended_opts(e2fsck_t ctx, const char *opts)
"and may take an argument which\n"
"is set off by an equals ('=') sign. "
"Valid extended options are:\n"
- "\tea_ver=<ea_version (1 or 2)>\n\n"), stderr);
+ "\tea_ver=<ea_version (1 or 2)>\n"
+ "\tuninit_groups\n"
+ "\tinit_groups\n\n"), stderr);
exit(1);
}
}
@@ -745,6 +747,7 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
if ((ctx->options & E2F_OPT_NO) && !bad_blocks_file &&
!cflag && !(ctx->options & E2F_OPT_COMPRESS_DIRS))
ctx->options |= E2F_OPT_READONLY;
+
ctx->io_options = strchr(argv[optind], '?');
if (ctx->io_options)
*ctx->io_options++ = 0;
@@ -842,7 +845,7 @@ sscanf_err:
static const char *my_ver_string = E2FSPROGS_VERSION;
static const char *my_ver_date = E2FSPROGS_DATE;
-
+
int main (int argc, char *argv[])
{
errcode_t retval = 0, orig_retval = 0;
@@ -1306,6 +1309,10 @@ no_journal:
}
}
+ if (sb->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM &&
+ !(ctx->options & E2F_OPT_READONLY))
+ ext2fs_set_gdt_csum(ctx->fs);
+
e2fsck_write_bitmaps(ctx);
#ifdef RESOURCE_TRACK
io_channel_flush(ctx->fs->io);
diff --git a/e2fsck/util.c b/e2fsck/util.c
index ba7ef4a..751ad78 100644
--- a/e2fsck/util.c
+++ b/e2fsck/util.c
@@ -29,6 +29,10 @@
#include <malloc.h>
#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
#include "e2fsck.h"
extern e2fsck_t e2fsck_global_ctx; /* Try your very best not to use this! */
@@ -532,3 +536,60 @@ int ext2_file_type(unsigned int mode)
return 0;
}
+
+#define STRIDE_LENGTH 8
+/*
+ * Helper function which zeros out _num_ blocks starting at _blk_. In
+ * case of an error, the details of the error is returned via _ret_blk_
+ * and _ret_count_ if they are non-NULL pointers. Returns 0 on
+ * success, and an error code on an error.
+ *
+ * As a special case, if the first argument is NULL, then it will
+ * attempt to free the static zeroizing buffer. (This is to keep
+ * programs that check for memory leaks happy.)
+ */
+errcode_t e2fsck_zero_blocks(ext2_filsys fs, blk_t blk, int num,
+ blk_t *ret_blk, int *ret_count)
+{
+ int j, count, next_update, next_update_incr;
+ static char *buf;
+ errcode_t retval;
+
+ /* If fs is null, clean up the static buffer and return */
+ if (!fs) {
+ if (buf) {
+ free(buf);
+ buf = 0;
+ }
+ return 0;
+ }
+ /* Allocate the zeroizing buffer if necessary */
+ if (!buf) {
+ buf = malloc(fs->blocksize * STRIDE_LENGTH);
+ if (!buf) {
+ com_err("malloc", ENOMEM,
+ _("while allocating zeroizing buffer"));
+ exit(1);
+ }
+ memset(buf, 0, fs->blocksize * STRIDE_LENGTH);
+ }
+ /* OK, do the write loop */
+ next_update = 0;
+ next_update_incr = num / 100;
+ if (next_update_incr < 1)
+ next_update_incr = 1;
+ for (j = 0; j < num; j += STRIDE_LENGTH, blk += STRIDE_LENGTH) {
+ count = num - j;
+ if (count > STRIDE_LENGTH)
+ count = STRIDE_LENGTH;
+ retval = io_channel_write_blk(fs->io, blk, count, buf);
+ if (retval) {
+ if (ret_count)
+ *ret_count = count;
+ if (ret_blk)
+ *ret_blk = blk;
+ return retval;
+ }
+ }
+ return 0;
+}
-
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists