diff options
Diffstat (limited to 'innobase')
-rw-r--r-- | innobase/fil/fil0fil.c | 70 |
1 files changed, 51 insertions, 19 deletions
diff --git a/innobase/fil/fil0fil.c b/innobase/fil/fil0fil.c index 0f5941ca0d9..773bd709fb7 100644 --- a/innobase/fil/fil0fil.c +++ b/innobase/fil/fil0fil.c @@ -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); } /************************************************************************ |