Commit ce22ebd0 authored by unknown's avatar unknown

fil0fil.c:

  Add fault tolerance in the scan of .ibd files at a crash recovery; formerly a single failure of readdir_get_next caused the rest of the directory to be skipped


innobase/fil/fil0fil.c:
  Add fault tolerance in the scan of .ibd files at a crash recovery; formerly a single failure of readdir_get_next caused the rest of the directory to be skipped
parent 78bdb7d5
......@@ -2924,6 +2924,44 @@ func_exit:
mem_free(filepath);
}
/***************************************************************************
A fault-tolerant function that tries to read the next file name in the
directory. We retry 100 times if os_file_readdir_next_file() returns -1. The
idea is to read as much good data as we can and jump over bad data. */
static
int
fil_file_readdir_next_file(
/*=======================*/
/* out: 0 if ok, -1 if error even after the
retries, 1 if at the end of the directory */
ulint* err, /* out: this is set to DB_ERROR if an error
was encountered, otherwise not changed */
const char* dirname,/* in: directory name or path */
os_file_dir_t dir, /* in: directory stream */
os_file_stat_t* info) /* in/out: buffer where the info is returned */
{
ulint i;
int ret;
for (i = 0; i < 100; i++) {
ret = os_file_readdir_next_file(dirname, dir, info);
if (ret != -1) {
return(ret);
}
fprintf(stderr,
"InnoDB: Error: os_file_readdir_next_file() returned -1 in\n"
"InnoDB: directory %s\n"
"InnoDB: Crash recovery may have failed for some .ibd files!\n", dirname);
*err = DB_ERROR;
}
return(-1);
}
/************************************************************************
At the server startup, if we need crash recovery, scans the database
directories under the MySQL datadir, looking for .ibd files. Those files are
......@@ -2944,6 +2982,7 @@ fil_load_single_table_tablespaces(void)
os_file_dir_t dbdir;
os_file_stat_t dbinfo;
os_file_stat_t fileinfo;
ulint err = DB_SUCCESS;
/* The datadir of MySQL is always the default directory of mysqld */
......@@ -2959,7 +2998,7 @@ fil_load_single_table_tablespaces(void)
/* Scan all directories under the datadir. They are the database
directories of MySQL. */
ret = os_file_readdir_next_file(fil_path_to_mysql_datadir, dir,
ret = fil_file_readdir_next_file(&err, fil_path_to_mysql_datadir, dir,
&dbinfo);
while (ret == 0) {
ulint len;
......@@ -2997,7 +3036,7 @@ fil_load_single_table_tablespaces(void)
/* We found a database directory; loop through it,
looking for possible .ibd files in it */
ret = os_file_readdir_next_file(dbpath, dbdir,
ret = fil_file_readdir_next_file(&err, dbpath, dbdir,
&fileinfo);
while (ret == 0) {
/* printf(
......@@ -3019,36 +3058,29 @@ fil_load_single_table_tablespaces(void)
dbinfo.name, fileinfo.name);
}
next_file_item:
ret = os_file_readdir_next_file(dbpath, dbdir,
ret = fil_file_readdir_next_file(&err,
dbpath, dbdir,
&fileinfo);
}
if (0 != os_file_closedir(dbdir)) {
fputs(
fputs(
"InnoDB: Warning: could not close database directory ", stderr);
ut_print_filename(stderr, dbpath);
putc('\n', stderr);
ut_print_filename(stderr, dbpath);
putc('\n', stderr);
err = DB_ERROR;
}
}
next_datadir_item:
ret = os_file_readdir_next_file(fil_path_to_mysql_datadir,
ret = fil_file_readdir_next_file(&err,
fil_path_to_mysql_datadir,
dir, &dbinfo);
}
mem_free(dbpath);
/* At the end of directory we should get 1 as the return value, -1
if there was an error */
if (ret != 1) {
fprintf(stderr,
"InnoDB: Error: os_file_readdir_next_file returned %d in MySQL datadir\n",
ret);
os_file_closedir(dir);
return(DB_ERROR);
}
if (0 != os_file_closedir(dir)) {
fprintf(stderr,
"InnoDB: Error: could not close MySQL datadir\n");
......@@ -3056,7 +3088,7 @@ next_datadir_item:
return(DB_ERROR);
}
return(DB_SUCCESS);
return(err);
}
/************************************************************************
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment