aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog14
-rw-r--r--doc/wydawca.texi31
-rw-r--r--src/config.c13
-rw-r--r--src/diskio.c65
-rw-r--r--src/wydawca.c3
-rw-r--r--src/wydawca.h1
6 files changed, 95 insertions, 32 deletions
diff --git a/ChangeLog b/ChangeLog
index 06c918c..c21ec22 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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 \

Return to:

Send suggestions and report system problems to the System administrator.