Sorry, got carried away and forgot to attach the patch...
Only in rsync-3.0.9: config.h.in
Only in rsync-3.0.9: configure.sh
diff -ur rsync-3.0.9/fileio.c rsync-3.0.9.1/fileio.c
--- rsync-3.0.9/fileio.c 2011-02-21 19:32:51.000000000 +0000
+++ rsync-3.0.9.1/fileio.c 2012-10-07 17:54:20.233482145 +0000
@@ -26,6 +26,9 @@
#endif
extern int sparse_files;
+extern int retry_errors;
+extern int retry_delay;
+extern int fill_byte;
static OFF_T sparse_seek = 0;
@@ -180,10 +183,12 @@
/* slide the read window in the file */
char *map_ptr(struct map_struct *map, OFF_T offset, int32 len)
{
- int32 nread;
+ int32 nread, retry_count;
OFF_T window_start, read_start;
int32 window_size, read_size, read_offset;
+ retry_count = 0;
+
if (len == 0)
return NULL;
if (len < 0) {
@@ -245,16 +250,46 @@
map->p_offset = window_start;
map->p_len = window_size;
+ memset(map->p + read_offset, fill_byte, read_size);
+
while (read_size > 0) {
nread = read(map->fd, map->p + read_offset, read_size);
- if (nread <= 0) {
- if (!map->status)
- map->status = nread ? errno : ENODATA;
- /* The best we can do is zero the buffer -- the file
- * has changed mid transfer! */
- memset(map->p + read_offset, 0, read_size);
+
+ if(nread == 0) {
+ rprintf(FERROR, "Unexpected EOF");
+ map->status = ENODATA;
break;
}
+
+ if(nread < read_size && errno) {
+ retry_count++;
+
+ map->status = errno;
+
+ if(retry_count > retry_errors) {
+ if(retry_errors > 0)
+ rprintf(FERROR, "Error retry finished after %d retries at offset %.0f.\n", retry_errors, (double)read_start);
+
+ break;
+ }
+
+ if(nread != -1) {
+ if(!map->status)
+ map->status = nread;
+ map->p_fd_offset += nread;
+ read_offset += nread;
+ read_size -= nread;
+ }
+
+ rprintf(FERROR, "Error reading %d bytes at offset %.0f, got %d.", read_size, (double)read_start, nread);
+ rprintf(FERROR, "Retrying in %d seconds.\n", retry_delay);
+
+ sleep(retry_delay);
+ errno = 0;
+
+ continue;
+ }
+
map->p_fd_offset += nread;
read_offset += nread;
read_size -= nread;
diff -ur rsync-3.0.9/flist.c rsync-3.0.9.1/flist.c
--- rsync-3.0.9/flist.c 2011-08-27 21:58:04.000000000 +0000
+++ rsync-3.0.9.1/flist.c 2012-09-28 16:20:50.199950493 +0000
@@ -71,6 +71,9 @@
extern struct stats stats;
extern char *filesfrom_host;
+extern int retry_errors;
+extern int retry_delay;
+
extern char curr_dir[MAXPATHLEN];
extern struct chmod_mode_struct *chmod_modes;
@@ -188,12 +191,24 @@
static int readlink_stat(const char *path, STRUCT_STAT *stp, char *linkbuf)
{
#ifdef SUPPORT_LINKS
+ int retry_count = 0;
+ int llen;
+
if (link_stat(path, stp, copy_dirlinks) < 0)
return -1;
if (S_ISLNK(stp->st_mode)) {
- int llen = readlink(path, linkbuf, MAXPATHLEN - 1);
- if (llen < 0)
+l1:
+ llen = readlink(path, linkbuf, MAXPATHLEN - 1);
+ if (llen < 0) {
+ retry_count++;
+ if(retry_count < retry_errors) {
+ rprintf(FERROR, "Error reading link at %s, retrying in %d seconds.\n", path, retry_delay);
+ sleep(retry_delay);
+ goto l1;
+ }
return -1;
+ }
+
linkbuf[llen] = '\0';
if (copy_unsafe_links && unsafe_symlink(linkbuf, path)) {
if (verbose > 1) {
diff -ur rsync-3.0.9/options.c rsync-3.0.9.1/options.c
--- rsync-3.0.9/options.c 2011-09-13 22:41:26.000000000 +0000
+++ rsync-3.0.9.1/options.c 2012-10-07 17:41:26.843409777 +0000
@@ -115,6 +115,9 @@
OFF_T max_size = 0;
OFF_T min_size = 0;
int ignore_errors = 0;
+int retry_errors = 1;
+int retry_delay = 15;
+int fill_byte = 0;
int modify_window = 0;
int blocking_io = -1;
int checksum_seed = 0;
@@ -374,6 +377,9 @@
rprintf(F," --delete-after receiver deletes after transfer, not during\n");
rprintf(F," --delete-excluded also delete excluded files from destination dirs\n");
rprintf(F," --ignore-errors delete even if there are I/O errors\n");
+ rprintf(F," --retry-errors=NUM On encountering an I/O error, retry this many times (1)\n");
+ rprintf(F," --retry-delay=NUM Delay this many seconds (15) before retrying errors\n");
+ rprintf(F," --fill-byte=NUM Fill read buffers with this byte. Default is 0x00.\n");
rprintf(F," --force force deletion of directories even if not empty\n");
rprintf(F," --max-delete=NUM don't delete more than NUM files\n");
rprintf(F," --max-size=SIZE don't transfer any file larger than SIZE\n");
@@ -558,6 +564,9 @@
{"force", 0, POPT_ARG_VAL, &force_delete, 1, 0, 0 },
{"no-force", 0, POPT_ARG_VAL, &force_delete, 0, 0, 0 },
{"ignore-errors", 0, POPT_ARG_VAL, &ignore_errors, 1, 0, 0 },
+ {"retry-errors", 0, POPT_ARG_LONG, &retry_errors, 0, 0, 0 },
+ {"retry-delay", 0, POPT_ARG_LONG, &retry_delay, 0, 0, 0 },
+ {"fill-byte", 0, POPT_ARG_INT, &fill_byte, 0, 0, 0 },
{"no-ignore-errors", 0, POPT_ARG_VAL, &ignore_errors, 0, 0, 0 },
{"max-delete", 0, POPT_ARG_INT, &max_delete, 0, 0, 0 },
{0, 'F', POPT_ARG_NONE, 0, 'F', 0, 0 },
@@ -1645,6 +1654,21 @@
}
}
+ if(retry_errors > 100 || retry_errors <0) {
+ snprintf(err_buf, sizeof err_buf, "--retry-errors=%d out of range (0 - 100)", retry_errors);
+ return(0);
+ }
+
+ if(retry_delay < 0 || retry_delay > 1600) {
+ snprintf(err_buf, sizeof err_buf, "--retry-delay=%d out of range (0 - 1600)", retry_delay);
+ return(0);
+ }
+
+ if(fill_byte < 0 || fill_byte > 255) {
+ snprintf(err_buf, sizeof err_buf, "--fill-byte=%d out of range (0 - 255)", fill_byte);
+ return(0);
+ }
+
if (files_from) {
char *h, *p;
int q;
Only in rsync-3.0.9: proto.h
Only in rsync-3.0.9: proto.h-tstamp
Only in rsync-3.0.9: rsync.1
Only in rsync-3.0.9: rsyncd.conf.5
Only in rsync-3.0.9.1: #rsync.yo~
diff -ur rsync-3.0.9/rsync.yo rsync-3.0.9.1/rsync.yo
--- rsync-3.0.9/rsync.yo 2011-09-23 16:13:53.000000000 +0000
+++ rsync-3.0.9.1/rsync.yo 2012-10-07 18:34:01.213715071 +0000
@@ -386,6 +386,9 @@
--delete-after receiver deletes after transfer, not during
--delete-excluded also delete excluded files from dest dirs
--ignore-errors delete even if there are I/O errors
+ --retry-errors=NUM reads will be retried NUM times on error
+ --retry-delay=NUM delay NUM seconds before retrying errors
+ --fill-byte=NUM fill read buffer with NUM before reading
--force force deletion of dirs even if not empty
--max-delete=NUM don't delete more than NUM files
--max-size=SIZE don't transfer any file larger than SIZE
@@ -1289,6 +1292,21 @@
dit(bf(--ignore-errors)) Tells bf(--delete) to go ahead and delete files
even when there are I/O errors.
+dit(bf(--retry-errors=NUM)) A read error may be retried NUM times in
+the case of a media error. Sections of a file that were not read will
+be filled with 0x00, or the byte specified with bf(--fill-byte).
+
+dit(bf(--retry-delay=NUM)) Before a failed read is retried, sleep for
+NUM seconds before retrying. This helps some targets that go nuts
+when there are errors, allowing the head to seek to a known position
+after a period of no activity.
+
+dit(bf(--fill-byte=NUM)) Before attempting a read, fill the buffer
+with NUM. Rsync attempts to read the whole file, regardless of the
+errors it encounters, leaving holes filled with 0x00 bytes unless this
+option is specfied. Broken files are only left in the destination
+directory if bf(--ignore-errors) is also specified on the commandline.
+
dit(bf(--force)) This option tells rsync to delete a non-empty directory
when it is to be replaced by a non-directory. This is only relevant if
deletions are not active (see bf(--delete) for details).
--
Please use reply-all for most replies to avoid omitting the mailing list.
To unsubscribe or change options: https://lists.samba.org/mailman/listinfo/rsync
Before posting, read: http://www.catb.org/~esr/faqs/smart-questions.html