diff options
-rw-r--r-- | ChangeLog | 14 | ||||
-rw-r--r-- | doc/wydawca.texi | 31 | ||||
-rw-r--r-- | src/config.c | 13 | ||||
-rw-r--r-- | src/diskio.c | 65 | ||||
-rw-r--r-- | src/wydawca.c | 3 | ||||
-rw-r--r-- | src/wydawca.h | 1 |
6 files changed, 95 insertions, 32 deletions
@@ -1,3 +1,12 @@ +2008-08-23 Sergey Poznyakoff <gray@gnu.org.ua> + + * src/wydawca.c (enable_sendfile): New global. + * src/wydawca.h: Likewise. + * src/config.c (enable-sendfile): New statement. + * src/diskio.c (copy_file): Use enable_sendfile to decide whether + to use sendfile. + * doc/wydawca.texi: Document enable-sendfile. + 2008-07-15 Sergey Poznyakoff <gray@gnu.org.ua> * src/wydawca.h (register_message_template): New prototype. @@ -5,8 +14,9 @@ * src/config.c (_cfg_raw_read): Remove unused variables. * src/directive.c (directive_version_in_range_p): Version is unsigned. * src/mail.c (do_notify): Remove unused variable. - * src/diskio.c (copy_file): Fall back to user-space copying if sendile - fails with EINVAL. Always remove destination file on failure. + * src/diskio.c (copy_file): Fall back to user-space copying if + sendfile fails with EINVAL. Always remove destination file on + failure. * src/triplet.c (expand_triplet_upload): Initialize exp->value. 2007-11-19 Sergey Poznyakoff <gray@gnu.org.ua> diff --git a/doc/wydawca.texi b/doc/wydawca.texi index 02d650e..7a4827a 100644 --- a/doc/wydawca.texi +++ b/doc/wydawca.texi @@ -386,6 +386,7 @@ configuration on a step-by-step basis. * syslog:: * sql:: * access methods:: +* copying:: * archivation:: * directory pairs:: * statistics:: @@ -729,6 +730,36 @@ verify-user sql default SELECT user.user_name \ @end smallexample @end deffn +@node copying +@section Copying +@cindex sendfile +@cindex Invalid value, warning message +@cindex Function not implemented, warning message + If compiled for GNU/Linux, @command{wydawca} tries to optimize disk +transfer operations by using @code{sendfile} system call. If it +fails, and the error is recoverable, @command{wydawca} falls back to +copying files using user space. This is indicated by one of the following +warning messages: + +@smallexample + sendfile: copying @var{source} to @var{dest} failed: Invalid value + + sendfile: copying @var{source} to @var{dest} failed: Function not + implemented +@end smallexample + +@kwindex enable-sendfile + If you encounter any of these, disable @code{sendfile} by adding the +following to your configuration file: + +@smallexample +enable-sendfile no +@end smallexample + + In particular, you need to disable sendfile when compiling +@command{wydawca} for Linux kernels starting from version 2.6.9 and +higher. + @node archivation @section Archivation @cindex archivation, defined diff --git a/src/config.c b/src/config.c index 4203bbb..9f6e401 100644 --- a/src/config.c +++ b/src/config.c @@ -1087,7 +1087,17 @@ cfg_notify_event (gsc_config_file_t *file, char *kw, char *val, void *unused) argcv_free (argc, argv); } - +static void +cfg_enable_sendfile (gsc_config_file_t *file, char *kw, char *val, + void *unused) +{ + if (get_bool (val, &enable_sendfile)) + { + file->error_msg (file->file_name, file->line, + "boolean value expected, but found `%s'", val); + file->error_count++; + } +} static struct gsc_config_keyword kw_handler[] = { @@ -1112,6 +1122,7 @@ static struct gsc_config_keyword kw_handler[] = { { "mail-admin-stat", cfg_mail_admin_stat }, { "define-message", cfg_define_message }, { "notify-event", cfg_notify_event }, + { "enable-sendfile", cfg_enable_sendfile }, { NULL } }; diff --git a/src/diskio.c b/src/diskio.c index 832b329..43191bb 100644 --- a/src/diskio.c +++ b/src/diskio.c @@ -144,7 +144,7 @@ copy_file (const char *file, const char *dst_file, uid_t uid, gid_t gid) { int in_fd, out_fd; struct stat st; - int rc = 1; + enum { copy_ok, copy_fallback, copy_failed } rc = copy_fallback; in_fd = open (file, O_RDONLY); @@ -173,27 +173,33 @@ copy_file (const char *file, const char *dst_file, uid_t uid, gid_t gid) } #ifdef USE_SENDFILE - { - off_t offset = 0; - ssize_t count; + if (enable_sendfile) + { + off_t offset = 0; + ssize_t count; - count = sendfile (out_fd, in_fd, &offset, st.st_size); - if (count == -1) - { - rc = 1; - logmsg (LOG_ERR, "copying %s to %s failed: %s", - file, dst_file, strerror (errno)); - } - else if (count < st.st_size) - { - rc = 1; - logmsg (LOG_ERR, "copying %s to %s failed: short write", - file, dst_file); - } - else - rc = 0; - } - if (rc && errno == EINVAL) + count = sendfile (out_fd, in_fd, &offset, st.st_size); + if (count == -1) + { + if (errno == EINVAL || errno == ENOSYS) + rc = copy_fallback; + else + rc = copy_failed; + logmsg ((rc == copy_fallback) ? LOG_WARNING : LOG_ERR, + "sendfile: copying %s to %s failed: %s", + file, dst_file, strerror (errno)); + } + else if (count < st.st_size) + { + rc = copy_failed; + logmsg (LOG_ERR, "copying %s to %s failed: short write", + file, dst_file); + } + else + rc = copy_ok; + } + + if (rc == copy_fallback) #endif { char *buf = NULL; @@ -206,7 +212,7 @@ copy_file (const char *file, const char *dst_file, uid_t uid, gid_t gid) if (bufsize == 0) xalloc_die (); - rc = 0; + rc = copy_ok; while (fsize > 0) { size_t rest; @@ -218,7 +224,7 @@ copy_file (const char *file, const char *dst_file, uid_t uid, gid_t gid) { logmsg (LOG_ERR, "unexpected error reading %s: %s", file, strerror (errno)); - rc = 1; + rc = copy_failed; break; } rest = write (out_fd, buf, rdbytes); @@ -226,13 +232,13 @@ copy_file (const char *file, const char *dst_file, uid_t uid, gid_t gid) { logmsg (LOG_ERR, "unexpected error writing to %s: %s", dst_file, strerror (errno)); - rc = 1; + rc = copy_failed; break; } else if (rest != rdbytes) { logmsg (LOG_ERR, "short write on %s", dst_file); - rc = 1; + rc = copy_failed; } fsize -= rdbytes; } @@ -241,9 +247,12 @@ copy_file (const char *file, const char *dst_file, uid_t uid, gid_t gid) close (in_fd); close (out_fd); - if (rc) - unlink (dst_file); - return rc; + if (rc != copy_ok) + { + unlink (dst_file); + return 1; + } + return 0; } /* Move FILE to DST_FILE. If they reside on different devices, use copy_file diff --git a/src/wydawca.c b/src/wydawca.c index 7c273dd..1187c5c 100644 --- a/src/wydawca.c +++ b/src/wydawca.c @@ -27,7 +27,8 @@ int syslog_include_prio; /* syslog messages include priority */ unsigned long print_stats; /* Print final statistics output */ time_t file_sweep_time = 0; char *tar_command_name = "tar"; - +int enable_sendfile = 1; /* Use sendfile by default */ + unsigned wydawca_stat[MAX_STAT]; void diff --git a/src/wydawca.h b/src/wydawca.h index d623e53..d4d1387 100644 --- a/src/wydawca.h +++ b/src/wydawca.h @@ -248,6 +248,7 @@ extern time_t file_sweep_time; /* Unlink stale file after this amount of time extern char *tar_command_name; /* Name of the tar command */ extern unsigned wydawca_stat[MAX_STAT]; extern unsigned long print_stats; +extern int enable_sendfile; #define UPDATE_STATS(what) \ do \ |