From 8b3e60523aa3d86583a1df54c81c9d480ea19740 Mon Sep 17 00:00:00 2001 From: Wayne Davison Date: Sun, 31 Aug 2008 09:03:50 -0700 Subject: [PATCH] Improved the fix that ensures that the generator gets notified about an I/O error for the incremental directory that generated the error. The PROTOCOL_VERSION was bumped to 31 to implement this. --- NEWS | 2 +- OLDNEWS | 2 +- flist.c | 42 ++++++++++++++++++++++++++++++++---------- generator.c | 5 ----- io.c | 8 -------- main.c | 5 ----- rsync.c | 15 +-------------- rsync.h | 7 ++++--- 8 files changed, 39 insertions(+), 47 deletions(-) diff --git a/NEWS b/NEWS index 02be9350..6703aa68 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,5 @@ NEWS for rsync 3.1.0 (UNRELEASED) -Protocol: 30 (unchanged) +Protocol: 31 (changed) Changes since 3.0.4: BUG FIXES: diff --git a/OLDNEWS b/OLDNEWS index bb0f17d2..33348a1b 100644 --- a/OLDNEWS +++ b/OLDNEWS @@ -2841,7 +2841,7 @@ Changes since 2.4.6: Partial Protocol History RELEASE DATE VER. DATE OF COMMIT* PROTOCOL - ?? ??? 2008 3.1.0 30 + ?? ??? 2008 3.1.0 31 Aug 2008 31 29 Jun 2008 3.0.3 30 08 Apr 2008 3.0.2 30 03 Apr 2008 3.0.1 30 diff --git a/flist.c b/flist.c index d11437fb..92e89a26 100644 --- a/flist.c +++ b/flist.c @@ -1916,7 +1916,12 @@ void send_extra_file_list(int f, int at_least) dp = F_DIR_NODE_P(file); } - write_byte(f, 0); + if (protocol_version < 31 || io_error == save_io_error || ignore_errors) + write_byte(f, 0); + else { + write_shortint(f, XMIT_EXTENDED_FLAGS|XMIT_IO_ERROR_ENDLIST); + write_int(f, io_error); + } if (need_unsorted_flist) { if (!(flist->sorted = new_array(struct file_struct *, flist->used))) @@ -1957,7 +1962,7 @@ void send_extra_file_list(int f, int at_least) } finish: - if (io_error != save_io_error && !ignore_errors) + if (io_error != save_io_error && protocol_version == 30 && !ignore_errors) send_msg_int(MSG_IO_ERROR, io_error); } @@ -2213,7 +2218,13 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) stats.flist_buildtime = 1; start_tv = end_tv; - write_byte(f, 0); /* Indicate end of file list */ + /* Indicate end of file list */ + if (protocol_version < 31 || io_error == 0 || ignore_errors) + write_byte(f, 0); + else { + write_shortint(f, XMIT_EXTENDED_FLAGS|XMIT_IO_ERROR_ENDLIST); + write_int(f, io_error); + } #ifdef SUPPORT_HARD_LINKS if (preserve_hard_links && protocol_version >= 30 && !inc_recurse) @@ -2251,7 +2262,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) /* send the io_error flag */ if (protocol_version < 30) write_int(f, ignore_errors ? 0 : io_error); - else if (io_error && !ignore_errors) + else if (io_error && protocol_version == 30 && !ignore_errors) send_msg_int(MSG_IO_ERROR, io_error); if (disable_buffering) @@ -2322,10 +2333,22 @@ struct file_list *recv_file_list(int f) while ((flags = read_byte(f)) != 0) { struct file_struct *file; - flist_expand(flist, 1); - if (protocol_version >= 28 && (flags & XMIT_EXTENDED_FLAGS)) flags |= read_byte(f) << 8; + + if (flags == (XMIT_EXTENDED_FLAGS|XMIT_IO_ERROR_ENDLIST)) { + int err; + if (protocol_version < 31) { + rprintf(FERROR, "Invalid flist flag: %x\n", flags); + exit_cleanup(RERR_PROTOCOL); + } + err = read_int(f); + if (!ignore_errors) + io_error |= err; + break; + } + + flist_expand(flist, 1); file = recv_file_entry(flist, flags, f); if (inc_recurse && S_ISDIR(file->mode)) { @@ -2389,10 +2412,9 @@ struct file_list *recv_file_list(int f) if (protocol_version < 30) { /* Recv the io_error flag */ - if (ignore_errors) - read_int(f); - else - io_error |= read_int(f); + int err = read_int(f); + if (!ignore_errors) + io_error |= err; } else if (inc_recurse && flist->ndx_start == 1) { if (!file_total || strcmp(flist->sorted[flist->low]->basename, ".") != 0) flist->parent_ndx = -1; diff --git a/generator.c b/generator.c index 5c3653f3..80e9826d 100644 --- a/generator.c +++ b/generator.c @@ -86,7 +86,6 @@ extern int unsort_ndx; extern int max_delete; extern int force_delete; extern int one_file_system; -extern int check_for_io_err; extern struct stats stats; extern dev_t filesystem_dev; extern mode_t orig_umask; @@ -2236,10 +2235,6 @@ void generate_files(int f_out, const char *local_name) dirdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp)); } else dirdev = MAKEDEV(0, 0); - /* We must be sure we've had a chance to receive an I/O - * error for this directory before we delete in it. */ - while (check_for_io_err && !cur_flist->next && !flist_eof) - wait_for_receiver(); delete_in_dir(fbuf, fp, &dirdev); } else change_local_filter_dir(fbuf, strlen(fbuf), F_DEPTH(fp)); diff --git a/io.c b/io.c index cc2561fe..1752d86f 100644 --- a/io.c +++ b/io.c @@ -63,7 +63,6 @@ int allowed_lull = 0; int ignore_timeout = 0; int batch_fd = -1; int msgdone_cnt = 0; -int check_for_io_err = 0; /* Ignore an EOF error if non-zero. See whine_about_eof(). */ int kluge_around_eof = 0; @@ -377,8 +376,6 @@ static void read_msg_fd(void) len = tag & 0xFFFFFF; tag = (tag >> 24) - MPLEX_BASE; - check_for_io_err = 0; - switch (tag) { case MSG_DONE: if (len < 0 || len > 1 || !am_generator) { @@ -413,9 +410,6 @@ static void read_msg_fd(void) } flist = recv_file_list(fd); flist->parent_ndx = IVAL(buf,0); - /* If the sender is going to send us an MSG_IO_ERROR value, it - * will always be the very next message following MSG_FLIST. */ - check_for_io_err = 1; #ifdef SUPPORT_HARD_LINKS if (preserve_hard_links) match_hard_links(flist); @@ -1063,8 +1057,6 @@ static int readfd_unbuffered(int fd, char *buf, size_t len) msg_bytes = tag & 0xFFFFFF; tag = (tag >> 24) - MPLEX_BASE; - check_for_io_err = 0; - switch (tag) { case MSG_DATA: if (msg_bytes > iobuf_in_siz) { diff --git a/main.c b/main.c index dc3c5334..c32457d4 100644 --- a/main.c +++ b/main.c @@ -64,11 +64,8 @@ extern int whole_file; extern int read_batch; extern int write_batch; extern int batch_fd; -extern int flist_eof; extern int filesfrom_fd; -extern int delete_during; extern int connect_timeout; -extern int check_for_io_err; extern pid_t cleanup_child_pid; extern unsigned int module_dirlen; extern struct stats stats; @@ -768,8 +765,6 @@ static int do_recv(int f_in, int f_out, char *local_name) exit_cleanup(RERR_IPC); } - check_for_io_err = inc_recurse && delete_during && !flist_eof; - if (pid == 0) { close(error_pipe[0]); if (f_in != f_out) diff --git a/rsync.c b/rsync.c index f26f2121..2d8e5e42 100644 --- a/rsync.c +++ b/rsync.c @@ -48,8 +48,6 @@ extern int flist_eof; extern int msgs2stderr; extern int keep_dirlinks; extern int make_backups; -extern int delete_during; -extern int check_for_io_err; extern struct file_list *cur_flist, *first_flist, *dir_flist; extern struct chmod_mode_struct *daemon_chmod_modes; #ifdef ICONV_OPTION @@ -254,15 +252,8 @@ int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar *type_ptr, while (1) { ndx = read_ndx(f_in); - if (ndx >= 0) { - if (check_for_io_err) { - /* Let generator know there was no I/O error. */ - send_msg_int(MSG_IO_ERROR, 0); - check_for_io_err = 0; - } + if (ndx >= 0) break; - } - check_for_io_err = 0; if (ndx == NDX_DONE) return ndx; if (!inc_recurse || am_sender) { @@ -306,10 +297,6 @@ int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar *type_ptr, stop_flist_forward(); if (!msgs2stderr) negate_output_levels(); /* restore info/debug output */ - /* If the sender is going to send us an MSG_IO_ERROR value, it - * will always be the very next message following a file list. */ - if (delete_during) - check_for_io_err = 1; } iflags = protocol_version >= 29 ? read_shortint(f_in) diff --git a/rsync.h b/rsync.h index 320d340c..c23e523d 100644 --- a/rsync.h +++ b/rsync.h @@ -60,6 +60,7 @@ #define XMIT_RDEV_MINOR_8_pre30 (1<<11) /* protocols 28 - 29 */ #define XMIT_GROUP_NAME_FOLLOWS (1<<11) /* protocols 30 - now */ #define XMIT_HLINK_FIRST (1<<12) /* protocols 30 - now (HLINKED files only) */ +#define XMIT_IO_ERROR_ENDLIST (1<<12) /* protocols 31 - now (w/XMIT_EXTENDED_FLAGS) */ /* These flags are used in the live flist data. */ @@ -90,12 +91,12 @@ == ((unsigned)(b2) & (unsigned)(mask))) /* update this if you make incompatible changes */ -#define PROTOCOL_VERSION 30 +#define PROTOCOL_VERSION 31 /* This is used when working on a new protocol version in CVS, and should * be a new non-zero value for each CVS change that affects the protocol. - * It must ALWAYS be 0 when the protocol goes final! */ -#define SUBPROTOCOL_VERSION 0 + * It must ALWAYS be 0 when the protocol goes final (and NEVER before)! */ +#define SUBPROTOCOL_VERSION 1 /* We refuse to interoperate with versions that are not in this range. * Note that we assume we'll work with later versions: the onus is on -- 2.34.1