320 lines
8.3 KiB
C
320 lines
8.3 KiB
C
/*
|
|
* Copyright 1996-2004 by Hans Reiser, licensing governed by
|
|
* reiserfsprogs/README
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif
|
|
|
|
#include "fsck.h"
|
|
#include "misc/malloc.h"
|
|
#include "util/misc.h"
|
|
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
|
|
#define ROLLBACK_FILE_START_MAGIC "_RollBackFileForReiserfsFSCK"
|
|
|
|
static struct block_handler * rollback_blocks_array;
|
|
static __u32 rollback_blocks_number = 0;
|
|
static FILE * s_rollback_file = 0;
|
|
static FILE * log_file;
|
|
static int do_rollback = 0;
|
|
|
|
static char * rollback_data;
|
|
static unsigned int rollback_blocksize;
|
|
|
|
void fsck_rollback_init (char * rollback_file, unsigned int *blocksize, FILE * log) {
|
|
char * string;
|
|
struct stat buf;
|
|
|
|
if (rollback_file == NULL)
|
|
return;
|
|
|
|
stat(rollback_file, &buf);
|
|
|
|
s_rollback_file = fopen (rollback_file, "w+");
|
|
if (s_rollback_file == NULL) {
|
|
fprintf (stderr, "Cannot create file %s, work without "
|
|
"a rollback file\n", rollback_file);
|
|
return;
|
|
}
|
|
|
|
rollback_blocksize = *blocksize;
|
|
|
|
string = ROLLBACK_FILE_START_MAGIC;
|
|
fwrite (string, 28, 1, s_rollback_file);
|
|
fwrite (&rollback_blocksize, sizeof(rollback_blocksize),
|
|
1, s_rollback_file);
|
|
|
|
fwrite (&rollback_blocks_number, sizeof(rollback_blocks_number),
|
|
1, s_rollback_file);
|
|
|
|
fflush(s_rollback_file);
|
|
|
|
rollback_data = misc_getmem(rollback_blocksize);
|
|
|
|
// printf("\ncheckmem1");
|
|
// fflush (stdout);
|
|
// checkmem (rollback_data, misc_memsize((char *)rollback_data));
|
|
// printf(" OK");
|
|
|
|
log_file = log;
|
|
if (log_file)
|
|
fprintf (log_file, "rollback: file (%s) initialize\n", rollback_file);
|
|
|
|
do_rollback = 0;
|
|
}
|
|
|
|
#if 0
|
|
static void erase_rollback_file (char * rollback_file) {
|
|
close_rollback_file ();
|
|
unlink (rollback_file);
|
|
}
|
|
#endif
|
|
|
|
int fsck_rollback_prep (char * rollback_file, FILE * log) {
|
|
char string [28];
|
|
struct stat buf;
|
|
|
|
if (rollback_file == NULL)
|
|
return -1;
|
|
|
|
if (stat(rollback_file, &buf)) {
|
|
fprintf (stderr, "Cannot stat rollback file (%s)\n", rollback_file);
|
|
return -1;
|
|
}
|
|
|
|
s_rollback_file = fopen (rollback_file, "r+");
|
|
if (s_rollback_file == NULL) {
|
|
fprintf (stderr, "Cannot open file (%s)\n", rollback_file);
|
|
return -1;
|
|
}
|
|
|
|
fread (string, 28, 1, s_rollback_file);
|
|
if (!strcmp (string, ROLLBACK_FILE_START_MAGIC)) {
|
|
fprintf (stderr, "Specified file (%s) does not look like "
|
|
"a rollback file\n", rollback_file);
|
|
|
|
fclose (s_rollback_file);
|
|
s_rollback_file = 0;
|
|
return -1;
|
|
}
|
|
|
|
fread (&rollback_blocksize, sizeof (rollback_blocksize),
|
|
1, s_rollback_file);
|
|
|
|
if (rollback_blocksize <= 0) {
|
|
fprintf(stderr, "rollback: wrong rollback blocksize, exit\n");
|
|
return -1;
|
|
}
|
|
|
|
log_file = log;
|
|
if (log_file)
|
|
fprintf (log_file, "rollback: file (%s) opened\n", rollback_file);
|
|
|
|
do_rollback = 1;
|
|
return 0;
|
|
}
|
|
|
|
void fsck_rollback_fini () {
|
|
if (s_rollback_file == 0)
|
|
return;
|
|
|
|
if (!do_rollback) {
|
|
if (fseek (s_rollback_file, 28 + sizeof(int), SEEK_SET) == (off_t)-1)
|
|
return;
|
|
|
|
fwrite (&rollback_blocks_number,
|
|
sizeof (rollback_blocksize),
|
|
1, s_rollback_file);
|
|
|
|
if (log_file != 0) {
|
|
fprintf (log_file, "rollback: %d blocks backed up\n",
|
|
rollback_blocks_number);
|
|
}
|
|
}
|
|
|
|
fclose (s_rollback_file);
|
|
|
|
misc_freemem (rollback_data);
|
|
misc_freemem (rollback_blocks_array);
|
|
/*
|
|
fprintf (stdout, "rollback: (%u) blocks saved, \n",
|
|
rollback_blocks_number);
|
|
|
|
for (i = 0; i < rollback_blocks_number; i++)
|
|
fprintf(stdout, "device (%Lu), block number (%u)\n",
|
|
rollback_blocks_array [i].device,
|
|
rollback_blocks_array [i].blocknr);
|
|
fprintf(stdout, "\n");
|
|
*/
|
|
|
|
}
|
|
|
|
void fsck_rollback (int fd_device, int fd_journal_device, FILE * progress) {
|
|
long long int offset;
|
|
|
|
struct stat buf;
|
|
int descriptor;
|
|
ssize_t retval;
|
|
int count_failed = 0;
|
|
int count_rollbacked = 0;
|
|
|
|
int b_dev;
|
|
int n_dev = 0;
|
|
int n_journal_dev = 0;
|
|
unsigned long total, done = 0;
|
|
|
|
if (fd_device == 0) {
|
|
fprintf(stderr, "rollback: unspecified device, exit\n");
|
|
return;
|
|
}
|
|
|
|
if (fd_journal_device) {
|
|
if (!fstat (fd_journal_device, &buf)) {
|
|
n_journal_dev = buf.st_rdev;
|
|
} else {
|
|
fprintf(stderr, "rollback: specified journal device "
|
|
"cannot be stated\n");
|
|
}
|
|
}
|
|
|
|
if (!fstat (fd_device, &buf)) {
|
|
n_dev = buf.st_rdev;
|
|
} else {
|
|
fprintf(stderr, "rollback: specified device cannot "
|
|
"be stated, exit\n");
|
|
return;
|
|
}
|
|
|
|
rollback_data = misc_getmem (rollback_blocksize);
|
|
// printf("\ncheckmem2");
|
|
// fflush (stdout);
|
|
// checkmem (rollback_data, misc_memsize((char *)rollback_data));
|
|
// printf(" OK");
|
|
|
|
fread (&rollback_blocks_number,
|
|
sizeof (rollback_blocks_number),
|
|
1, s_rollback_file);
|
|
|
|
total = rollback_blocks_number;
|
|
|
|
while (1) {
|
|
if (!fsck_quiet(fs)) {
|
|
util_misc_progress (progress, &done,
|
|
rollback_blocks_number,
|
|
1, 0);
|
|
}
|
|
|
|
descriptor = 0;
|
|
if ((retval = fread (&b_dev, sizeof (b_dev),
|
|
1, s_rollback_file)) <= 0)
|
|
{
|
|
if (retval)
|
|
fprintf (stderr, "rollback: fread: %s\n", strerror (errno));
|
|
|
|
break;
|
|
}
|
|
|
|
if ((retval = fread (&offset, sizeof (offset),
|
|
1, s_rollback_file)) <= 0)
|
|
{
|
|
if (retval)
|
|
fprintf (stderr, "rollback: fread: %s\n", strerror (errno));
|
|
|
|
break;
|
|
}
|
|
|
|
if ((retval = fread (rollback_data, rollback_blocksize,
|
|
1, s_rollback_file)) <= 0)
|
|
{
|
|
if (retval)
|
|
fprintf (stderr, "rollback: fread: %s\n", strerror (errno));
|
|
|
|
break;
|
|
}
|
|
|
|
if (n_dev == b_dev)
|
|
descriptor = fd_device;
|
|
|
|
if ((n_journal_dev) && (n_journal_dev == b_dev))
|
|
descriptor = fd_journal_device;
|
|
|
|
if (descriptor == 0) {
|
|
fprintf(stderr, "rollback: block from unknown "
|
|
"device, skip block\n");
|
|
count_failed ++;
|
|
continue;
|
|
}
|
|
|
|
if (lseek (descriptor, offset, SEEK_SET) == (off_t)-1) {
|
|
fprintf(stderr, "device cannot be lseeked, skip block\n");
|
|
count_failed ++;
|
|
continue;
|
|
}
|
|
|
|
if (write (descriptor, rollback_data, rollback_blocksize) == -1) {
|
|
fprintf (stderr, "rollback: write %d bytes returned error "
|
|
"(block=%lld, dev=%d): %s\n", rollback_blocksize,
|
|
offset/rollback_blocksize, b_dev, strerror (errno));
|
|
count_failed ++;
|
|
} else {
|
|
count_rollbacked ++;
|
|
/*if you want to know what gets rollbacked, uncomment it*/
|
|
/* if (log_file != 0 && log_file != stdout)
|
|
fprintf (log_file, "rollback: block %Lu of "
|
|
"device %Lu was restored\n",
|
|
(unsigned long long)offset/rollback_blocksize, b_dev);
|
|
|
|
|
|
fprintf (stdout, "rollback: block (%Ld) written\n",
|
|
(long long int)offset/rollback_blocksize);
|
|
*/
|
|
}
|
|
}
|
|
|
|
printf ("\n");
|
|
|
|
if (log_file != 0) {
|
|
fprintf (log_file, "rollback: (%u) blocks restored\n",
|
|
count_rollbacked);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
static void rollback__mark_block_saved (struct block_handler * rb_e) {
|
|
if (rollback_blocks_array == NULL)
|
|
rollback_blocks_array =
|
|
misc_getmem (ROLLBACK__INCREASE_BLOCK_NUMBER * sizeof (*rb_e));
|
|
|
|
if (rollback_blocks_number ==
|
|
misc_memsize ((void *)rollback_blocks_array) / sizeof (*rb_e))
|
|
{
|
|
rollback_blocks_array =
|
|
misc_expandmem (rollback_blocks_array,
|
|
misc_memsize((void *)rollback_blocks_array),
|
|
ROLLBACK__INCREASE_BLOCK_NUMBER *
|
|
sizeof (*rb_e));
|
|
}
|
|
|
|
// checkmem ((char *)rollback_blocks_array,
|
|
misc_memsize((char *)rollback_blocks_array));
|
|
|
|
rollback_blocks_array[rollback_blocks_number] = *rb_e;
|
|
rollback_blocks_number ++;
|
|
qsort (rollback_blocks_array, rollback_blocks_number,
|
|
sizeof (*rb_e), rollback_compare);
|
|
|
|
// printf("\ncheckmem3");
|
|
// fflush (stdout);
|
|
// checkmem ((char *)rollback_blocks_array,
|
|
misc_memsize((char *)rollback_blocks_array));
|
|
// printf(" OK");
|
|
}
|
|
*/
|
|
|