mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-10-21 21:34:17 -04:00
Moved the code that checks for finished file-lists, for finished "redo"
sends, and finished hard-links into check_for_finished_files(), a new function that takes the place of check_for_finished_hlinks(). This lets us signal the sender more rapidly when a file-list is done (which ensures that it sends us more work to do in a timely manner), and also avoids two potential deadlocks in the old code.
This commit is contained in:
1 parent
7a2fa0c2d3
commit
7730114b30
1 file changed
+114
-134
+114
-134
@@ -49,7 +49,7 @@ extern int delete_mode;
|
||||
extern int delete_before;
|
||||
extern int delete_during;
|
||||
extern int delete_after;
|
||||
extern int done_cnt;
|
||||
extern int msgdone_cnt;
|
||||
extern int ignore_errors;
|
||||
extern int remove_source_files;
|
||||
extern int delay_updates;
|
||||
@@ -105,7 +105,10 @@ static int deletion_count = 0; /* used to implement --max-delete */
|
||||
static int deldelay_size = 0, deldelay_cnt = 0;
|
||||
static char *deldelay_buf = NULL;
|
||||
static int deldelay_fd = -1;
|
||||
static BOOL solo_file = 0;
|
||||
static int lull_mod;
|
||||
static int dir_tweaking;
|
||||
static int need_retouch_dir_times;
|
||||
static const char *solo_file = NULL;
|
||||
|
||||
/* For calling delete_item() and delete_dir_contents(). */
|
||||
#define DEL_RECURSE (1<<1) /* recurse */
|
||||
@@ -777,24 +780,6 @@ static int find_fuzzy(struct file_struct *file, struct file_list *dirlist)
|
||||
return lowest_j;
|
||||
}
|
||||
|
||||
#ifdef SUPPORT_HARD_LINKS
|
||||
void check_for_finished_hlinks(int itemizing, enum logcode code)
|
||||
{
|
||||
struct file_struct *file;
|
||||
struct file_list *flist;
|
||||
char fbuf[MAXPATHLEN];
|
||||
int ndx;
|
||||
|
||||
while ((ndx = get_hlink_num()) != -1) {
|
||||
flist = flist_for_ndx(ndx);
|
||||
assert(flist != NULL);
|
||||
file = flist->files[ndx];
|
||||
assert(file->flags & FLAG_HLINKED);
|
||||
finish_hard_link(file, f_name(file, fbuf), NULL, itemizing, code, -1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This is only called for regular files. We return -2 if we've finished
|
||||
* handling the file, -1 if no dest-linking occurred, or a non-negative
|
||||
* value if we found an alternate basis file. */
|
||||
@@ -1648,8 +1633,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static void touch_up_dirs(struct file_list *flist, int ndx,
|
||||
int need_retouch_dir_times, int lull_mod)
|
||||
static void touch_up_dirs(struct file_list *flist, int ndx)
|
||||
{
|
||||
struct file_struct *file;
|
||||
char *fname;
|
||||
@@ -1682,18 +1666,89 @@ static void touch_up_dirs(struct file_list *flist, int ndx,
|
||||
}
|
||||
}
|
||||
|
||||
void generate_files(int f_out, char *local_name)
|
||||
void check_for_finished_files(int itemizing, enum logcode code, int check_redo)
|
||||
{
|
||||
struct file_struct *file;
|
||||
struct file_list *flist;
|
||||
char fbuf[MAXPATHLEN];
|
||||
int ndx;
|
||||
|
||||
#ifdef SUPPORT_HARD_LINKS
|
||||
while (preserve_hard_links && (ndx = get_hlink_num()) != -1) {
|
||||
flist = flist_for_ndx(ndx);
|
||||
assert(flist != NULL);
|
||||
file = flist->files[ndx];
|
||||
assert(file->flags & FLAG_HLINKED);
|
||||
finish_hard_link(file, f_name(file, fbuf), NULL, itemizing, code, -1);
|
||||
}
|
||||
#endif
|
||||
|
||||
while (check_redo && (ndx = get_redo_num()) != -1) {
|
||||
csum_length = SUM_LENGTH;
|
||||
max_size = -max_size;
|
||||
min_size = -min_size;
|
||||
ignore_existing = -ignore_existing;
|
||||
ignore_non_existing = -ignore_non_existing;
|
||||
update_only = -update_only;
|
||||
always_checksum = -always_checksum;
|
||||
size_only = -size_only;
|
||||
append_mode = -append_mode;
|
||||
make_backups = -make_backups; /* avoid dup backup w/inplace */
|
||||
ignore_times++;
|
||||
|
||||
flist = cur_flist;
|
||||
cur_flist = flist_for_ndx(ndx);
|
||||
ndx -= cur_flist->ndx_start;
|
||||
|
||||
file = cur_flist->files[ndx];
|
||||
if (solo_file)
|
||||
strlcpy(fbuf, solo_file, sizeof fbuf);
|
||||
else
|
||||
f_name(file, fbuf);
|
||||
recv_generator(fbuf, file, ndx, itemizing, code, sock_f_out);
|
||||
cur_flist->to_redo--;
|
||||
|
||||
cur_flist = flist;
|
||||
|
||||
csum_length = SHORT_SUM_LENGTH;
|
||||
max_size = -max_size;
|
||||
min_size = -min_size;
|
||||
ignore_existing = -ignore_existing;
|
||||
ignore_non_existing = -ignore_non_existing;
|
||||
update_only = -update_only;
|
||||
always_checksum = -always_checksum;
|
||||
size_only = -size_only;
|
||||
append_mode = -append_mode;
|
||||
make_backups = -make_backups;
|
||||
ignore_times--;
|
||||
}
|
||||
|
||||
while (cur_flist != first_flist) { /* only possible with inc_recurse */
|
||||
if (first_flist->in_progress || first_flist->to_redo)
|
||||
break;
|
||||
|
||||
if (!read_batch)
|
||||
write_ndx(sock_f_out, NDX_DONE);
|
||||
|
||||
if (delete_during == 2 || !dir_tweaking) {
|
||||
/* Skip directory touch-up. */
|
||||
} else if (first_flist->ndx_start != 0)
|
||||
touch_up_dirs(dir_flist, first_flist->parent_ndx);
|
||||
else if (relative_paths && implied_dirs)
|
||||
touch_up_dirs(first_flist, -1);
|
||||
|
||||
flist_free(first_flist); /* updates first_flist */
|
||||
}
|
||||
}
|
||||
|
||||
void generate_files(int f_out, const char *local_name)
|
||||
{
|
||||
int i;
|
||||
char fbuf[MAXPATHLEN];
|
||||
int itemizing;
|
||||
enum logcode code;
|
||||
struct file_list *next_flist;
|
||||
int lull_mod = allowed_lull * 5;
|
||||
int need_retouch_dir_times = preserve_times && !omit_dir_times;
|
||||
int need_retouch_dir_perms = 0;
|
||||
int save_do_progress = do_progress;
|
||||
int dir_tweaking = !(list_only || local_name || dry_run);
|
||||
|
||||
if (protocol_version >= 29) {
|
||||
itemizing = 1;
|
||||
@@ -1712,12 +1767,15 @@ void generate_files(int f_out, char *local_name)
|
||||
maybe_ATTRS_REPORT = ATTRS_REPORT;
|
||||
code = FINFO;
|
||||
}
|
||||
solo_file = local_name != NULL;
|
||||
solo_file = local_name;
|
||||
dir_tweaking = !(list_only || solo_file || dry_run);
|
||||
need_retouch_dir_times = preserve_times && !omit_dir_times;
|
||||
lull_mod = allowed_lull * 5;
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "generator starting pid=%ld\n", (long)getpid());
|
||||
|
||||
if (delete_before && !local_name && cur_flist->count > 0)
|
||||
if (delete_before && !solo_file && cur_flist->count > 0)
|
||||
do_delete_pass(cur_flist);
|
||||
if (delete_during == 2) {
|
||||
deldelay_size = BIGPATHBUFLEN * 4;
|
||||
@@ -1761,8 +1819,8 @@ void generate_files(int f_out, char *local_name)
|
||||
if (!F_IS_ACTIVE(file))
|
||||
continue;
|
||||
|
||||
if (local_name)
|
||||
strlcpy(fbuf, local_name, sizeof fbuf);
|
||||
if (solo_file)
|
||||
strlcpy(fbuf, solo_file, sizeof fbuf);
|
||||
else
|
||||
f_name(file, fbuf);
|
||||
recv_generator(fbuf, file, i, itemizing, code, f_out);
|
||||
@@ -1775,7 +1833,7 @@ void generate_files(int f_out, char *local_name)
|
||||
if (!am_root && S_ISDIR(file->mode)
|
||||
&& !(file->mode & S_IWUSR) && dir_tweaking) {
|
||||
mode_t mode = file->mode | S_IWUSR;
|
||||
char *fname = local_name ? local_name : fbuf;
|
||||
const char *fname = solo_file ? solo_file : fbuf;
|
||||
if (do_chmod(fname, mode) < 0) {
|
||||
rsyserr(FERROR, errno,
|
||||
"failed to modify permissions on %s",
|
||||
@@ -1785,10 +1843,7 @@ void generate_files(int f_out, char *local_name)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_HARD_LINKS
|
||||
if (preserve_hard_links)
|
||||
check_for_finished_hlinks(itemizing, code);
|
||||
#endif
|
||||
check_for_finished_files(itemizing, code, inc_recurse);
|
||||
|
||||
if (allowed_lull && !(i % lull_mod))
|
||||
maybe_send_keepalive();
|
||||
@@ -1797,99 +1852,26 @@ void generate_files(int f_out, char *local_name)
|
||||
}
|
||||
|
||||
if (!inc_recurse) {
|
||||
if (delete_during)
|
||||
delete_in_dir(NULL, NULL, NULL, &dev_zero);
|
||||
phase++;
|
||||
if (verbose > 2) {
|
||||
rprintf(FINFO, "generate_files phase=%d\n",
|
||||
phase);
|
||||
}
|
||||
|
||||
write_ndx(f_out, NDX_DONE);
|
||||
}
|
||||
|
||||
csum_length = SUM_LENGTH;
|
||||
max_size = -max_size;
|
||||
min_size = -min_size;
|
||||
ignore_existing = -ignore_existing;
|
||||
ignore_non_existing = -ignore_non_existing;
|
||||
update_only = -update_only;
|
||||
always_checksum = -always_checksum;
|
||||
size_only = -size_only;
|
||||
append_mode = -append_mode;
|
||||
make_backups = -make_backups; /* avoid dup backup w/inplace */
|
||||
ignore_times++;
|
||||
|
||||
/* Files can cycle through the system more than once
|
||||
* to catch initial checksum errors. */
|
||||
while (!done_cnt) {
|
||||
struct file_struct *file;
|
||||
struct file_list *save_flist;
|
||||
|
||||
check_for_finished_hlinks(itemizing, code);
|
||||
|
||||
if ((i = get_redo_num()) == -1) {
|
||||
if (inc_recurse)
|
||||
break;
|
||||
wait_for_receiver();
|
||||
continue;
|
||||
}
|
||||
|
||||
save_flist = cur_flist;
|
||||
cur_flist = flist_for_ndx(i);
|
||||
file = cur_flist->files[i];
|
||||
if (local_name)
|
||||
strlcpy(fbuf, local_name, sizeof fbuf);
|
||||
else
|
||||
f_name(file, fbuf);
|
||||
recv_generator(fbuf, file, i, itemizing, code, f_out);
|
||||
cur_flist->to_redo--;
|
||||
cur_flist = save_flist;
|
||||
}
|
||||
|
||||
csum_length = SHORT_SUM_LENGTH;
|
||||
max_size = -max_size;
|
||||
min_size = -min_size;
|
||||
ignore_existing = -ignore_existing;
|
||||
ignore_non_existing = -ignore_non_existing;
|
||||
update_only = -update_only;
|
||||
always_checksum = -always_checksum;
|
||||
size_only = -size_only;
|
||||
append_mode = -append_mode;
|
||||
make_backups = -make_backups;
|
||||
ignore_times--;
|
||||
|
||||
if (!inc_recurse)
|
||||
break;
|
||||
|
||||
while (!cur_flist->next && !flist_eof)
|
||||
wait_for_receiver();
|
||||
next_flist = cur_flist->next;
|
||||
while (first_flist != next_flist) {
|
||||
if (first_flist->in_progress || first_flist->to_redo) {
|
||||
if (next_flist)
|
||||
break;
|
||||
wait_for_receiver();
|
||||
continue;
|
||||
}
|
||||
|
||||
cur_flist = first_flist;
|
||||
if (delete_during == 2 || !dir_tweaking) {
|
||||
/* Skip directory touch-up. */
|
||||
} else if (cur_flist->ndx_start != 0) {
|
||||
touch_up_dirs(dir_flist, cur_flist->parent_ndx,
|
||||
need_retouch_dir_times, lull_mod);
|
||||
} else if (relative_paths && implied_dirs) {
|
||||
touch_up_dirs(cur_flist, -1,
|
||||
need_retouch_dir_times, lull_mod);
|
||||
}
|
||||
|
||||
flist_free(first_flist); /* updates cur_flist & first_flist */
|
||||
|
||||
if (!read_batch)
|
||||
write_ndx(f_out, NDX_DONE);
|
||||
}
|
||||
} while ((cur_flist = next_flist) != NULL);
|
||||
|
||||
while (!cur_flist->next && !flist_eof) {
|
||||
check_for_finished_files(itemizing, code, 1);
|
||||
wait_for_receiver();
|
||||
}
|
||||
} while ((cur_flist = cur_flist->next) != NULL);
|
||||
|
||||
if (delete_during)
|
||||
delete_in_dir(NULL, NULL, NULL, &dev_zero);
|
||||
phase++;
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "generate_files phase=%d\n", phase);
|
||||
|
||||
while (!msgdone_cnt) {
|
||||
check_for_finished_files(itemizing, code, 1);
|
||||
wait_for_receiver();
|
||||
}
|
||||
|
||||
phase++;
|
||||
if (verbose > 2)
|
||||
@@ -1901,8 +1883,8 @@ void generate_files(int f_out, char *local_name)
|
||||
write_ndx(f_out, NDX_DONE);
|
||||
|
||||
/* Read MSG_DONE for the redo phase (and any prior messages). */
|
||||
while (done_cnt <= 1) {
|
||||
check_for_finished_hlinks(itemizing, code);
|
||||
while (msgdone_cnt <= 1) {
|
||||
check_for_finished_files(itemizing, code, 0);
|
||||
wait_for_receiver();
|
||||
}
|
||||
|
||||
@@ -1913,21 +1895,19 @@ void generate_files(int f_out, char *local_name)
|
||||
if (delay_updates)
|
||||
write_ndx(f_out, NDX_DONE);
|
||||
/* Read MSG_DONE for delay-updates phase & prior messages. */
|
||||
while (done_cnt == 2)
|
||||
while (msgdone_cnt == 2)
|
||||
wait_for_receiver();
|
||||
}
|
||||
|
||||
do_progress = save_do_progress;
|
||||
if (delete_during == 2)
|
||||
do_delayed_deletions(fbuf);
|
||||
if (delete_after && !local_name && file_total > 0)
|
||||
if (delete_after && !solo_file && file_total > 0)
|
||||
do_delete_pass(cur_flist);
|
||||
|
||||
if ((need_retouch_dir_perms || need_retouch_dir_times)
|
||||
&& dir_tweaking && (!inc_recurse || delete_during == 2)) {
|
||||
touch_up_dirs(inc_recurse ? dir_flist : cur_flist, -1,
|
||||
need_retouch_dir_times, lull_mod);
|
||||
}
|
||||
&& dir_tweaking && (!inc_recurse || delete_during == 2))
|
||||
touch_up_dirs(inc_recurse ? dir_flist : cur_flist, -1);
|
||||
|
||||
if (max_delete >= 0 && deletion_count > max_delete) {
|
||||
rprintf(FINFO,
|
||||
|
||||
Reference in new issue
Block a user