From: didg Date: Sun, 25 Oct 2009 09:47:03 +0000 (+0000) Subject: on linux put sendfile back X-Git-Tag: before-ipv6~36 X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=netatalk.git;a=commitdiff_plain;h=d81ea56449b54aaeccf8bba1dc7ae88773268c33 on linux put sendfile back --- diff --git a/configure.in b/configure.in index 70b3f3e0..b643b90b 100644 --- a/configure.in +++ b/configure.in @@ -1,4 +1,4 @@ -dnl $Id: configure.in,v 1.222 2009-10-23 14:09:50 franklahm Exp $ +dnl $Id: configure.in,v 1.223 2009-10-25 09:47:03 didg Exp $ dnl configure.in for netatalk AC_INIT(etc/afpd/main.c) @@ -708,15 +708,14 @@ fi AC_DEFINE(HAVE_BROKEN_DBTOB, 1, [Define if dbtob is broken]) netatalk_cv_linux_sendfile=no -dnl disable this for now, code doesn't use sendfile anyway -dnl AC_ARG_ENABLE(sendfile, -dnl [ --enable-sendfile use sendfile syscall default (no) ],[ -dnl if test "$enableval" = "yes"; then -dnl netatalk_cv_linux_sendfile=yes -dnl fi -dnl AC_MSG_RESULT([enabling sendfile syscall]) -dnl ] -dnl ) + AC_ARG_ENABLE(sendfile, + [ --enable-sendfile use sendfile syscall default (no) ],[ + if test "$enableval" = "yes"; then + netatalk_cv_linux_sendfile=yes + fi + AC_MSG_RESULT([enabling sendfile syscall]) + ] + ) if test x"$netatalk_cv_linux_sendfile" = "xyes"; then AC_CACHE_CHECK([for linux sendfile support],netatalk_cv_HAVE_SENDFILE,[ diff --git a/etc/afpd/desktop.c b/etc/afpd/desktop.c index 060b68dc..af226447 100644 --- a/etc/afpd/desktop.c +++ b/etc/afpd/desktop.c @@ -1,5 +1,5 @@ /* - * $Id: desktop.c,v 1.42 2009-10-22 13:40:11 franklahm Exp $ + * $Id: desktop.c,v 1.43 2009-10-25 09:47:03 didg Exp $ * * See COPYRIGHT. * @@ -506,7 +506,7 @@ int afp_geticon(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t while (*rbuflen > 0) { #ifdef WITH_SENDFILE if (!obj->options.flags & OPTION_DEBUG) { - if (sys_sendfile(dsi->socket, si.sdt_fd, &offset, dsi->datasize) < 0) { + if (dsi_stream_read_file(dsi, si.sdt_fd, offset, dsi->datasize) < 0) { switch (errno) { case ENOSYS: case EINVAL: /* there's no guarantee that all fs support sendfile */ @@ -515,7 +515,10 @@ int afp_geticon(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t goto geticon_exit; } } - goto geticon_done; + else { + dsi_readdone(dsi); + return AFP_OK; + } } #endif buflen = read(si.sdt_fd, rbuf, *rbuflen); @@ -529,7 +532,7 @@ int afp_geticon(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen = buflen; } - + dsi_readdone(dsi); return AFP_OK; diff --git a/etc/afpd/fork.c b/etc/afpd/fork.c index 07ce3ab1..3c1e8756 100644 --- a/etc/afpd/fork.c +++ b/etc/afpd/fork.c @@ -1,5 +1,5 @@ /* - * $Id: fork.c,v 1.68 2009-10-25 06:12:51 didg Exp $ + * $Id: fork.c,v 1.69 2009-10-25 09:47:04 didg Exp $ * * Copyright (c) 1990,1993 Regents of The University of Michigan. * All Rights Reserved. See COPYRIGHT. @@ -931,10 +931,12 @@ static int read_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, si *rbuflen = cc; /* due to the nature of afp packets, we have to exit if we get an error. we can't do this with translation on. */ -#if 0 /* ifdef WITH_SENDFILE */ - /* FIXME with OS X deadlock partial workaround we can't use sendfile */ +#ifdef WITH_SENDFILE if (!(xlate || Debug(obj) )) { - if (ad_readfile(ofork->of_ad, eid, dsi->socket, offset, dsi->datasize) < 0) { + int fd; + + fd = ad_readfile_init(ofork->of_ad, eid, &offset, 0); + if (dsi_stream_read_file(dsi, fd, offset, dsi->datasize) < 0) { if (errno == EINVAL || errno == ENOSYS) goto afp_read_loop; else { diff --git a/include/atalk/adouble.h b/include/atalk/adouble.h index 685c548c..467f4118 100644 --- a/include/atalk/adouble.h +++ b/include/atalk/adouble.h @@ -1,5 +1,5 @@ /* - * $Id: adouble.h,v 1.47 2009-10-21 13:28:17 didg Exp $ + * $Id: adouble.h,v 1.48 2009-10-25 09:47:04 didg Exp $ * Copyright (c) 1990,1991 Regents of The University of Michigan. * All Rights Reserved. * @@ -543,8 +543,9 @@ extern u_int32_t ad_forcegetid (struct adouble *adp); #endif #ifdef WITH_SENDFILE -extern ssize_t ad_readfile (const struct adouble *, const int, - const int, off_t, const size_t); +extern int ad_readfile_init(const struct adouble *ad, + const int eid, off_t *off, + const int end); #endif #if 0 diff --git a/include/atalk/dsi.h b/include/atalk/dsi.h index de7beaf8..0c40f1f1 100644 --- a/include/atalk/dsi.h +++ b/include/atalk/dsi.h @@ -169,6 +169,10 @@ extern size_t dsi_stream_read (DSI *, void *, const size_t); extern int dsi_stream_send (DSI *, void *, size_t); extern int dsi_stream_receive (DSI *, void *, const size_t, size_t *); +#ifdef WITH_SENDFILE +extern ssize_t dsi_stream_read_file(DSI *, int, off_t off, const size_t len); +#endif + /* client writes -- dsi_write.c */ extern size_t dsi_writeinit (DSI *, void *, const size_t); extern size_t dsi_write (DSI *, void *, const size_t); diff --git a/libatalk/adouble/ad_sendfile.c b/libatalk/adouble/ad_sendfile.c index b4b63a94..48d99346 100644 --- a/libatalk/adouble/ad_sendfile.c +++ b/libatalk/adouble/ad_sendfile.c @@ -1,5 +1,5 @@ /* - * $Id: ad_sendfile.c,v 1.9 2008-12-03 18:35:44 didg Exp $ + * $Id: ad_sendfile.c,v 1.10 2009-10-25 09:47:04 didg Exp $ * * Copyright (c) 1999 Adrian Sun (asun@zoology.washington.edu) * All rights reserved. See COPYRIGHT. @@ -43,7 +43,6 @@ #include #include - #include "ad_private.h" #if defined(LINUX_BROKEN_SENDFILE_API) @@ -52,8 +51,9 @@ extern int32_t sendfile (int fdout, int fdin, int32_t *offset, u_int32_t count); ssize_t sys_sendfile(int tofd, int fromfd, off_t *offset, size_t count) { -u_int32_t small_total = 0; +u_int32_t small_total; int32_t small_offset; +int32_t nwritten; /* * Fix for broken Linux 2.4 systems with no working sendfile64(). @@ -66,22 +66,13 @@ int32_t small_offset; errno = ENOSYS; return -1; } - small_total = (u_int32_t)count; small_offset = (int32_t)*offset; - - while (small_total) { - int32_t nwritten; - do { - nwritten = sendfile(tofd, fromfd, &small_offset, small_total); - } while (nwritten == -1 && errno == EINTR); - if (nwritten == -1) - return -1; - if (nwritten == 0) - return -1; /* I think we're at EOF here... */ - small_total -= nwritten; - } - *offset += count; - return count; + small_total = (u_int32_t)count; + nwritten = sendfile(tofd, fromfd, &small_offset, small_total); + if (nwritten > = 0) + *offset += nwritten; + + return nwritten; } #elif defined(SENDFILE_FLAVOR_LINUX) @@ -89,26 +80,13 @@ int32_t small_offset; ssize_t sys_sendfile(int tofd, int fromfd, off_t *offset, size_t count) { -size_t total=0; - - total = count; - while (total) { - ssize_t nwritten; - do { - nwritten = sendfile(tofd, fromfd, offset, total); - } while (nwritten == -1 && errno == EINTR); - if (nwritten == -1) - return -1; - if (nwritten == 0) - return -1; /* I think we're at EOF here... */ - total -= nwritten; - } - return count; + return sendfile(tofd, fromfd, offset, count); } #elif defined(SENDFILE_FLAVOR_BSD ) /* FIXME untested */ +#error sendfile semantic broken #include ssize_t sys_sendfile(int tofd, int fromfd, off_t *offset, size_t count) { @@ -140,7 +118,7 @@ ssize_t sys_sendfile(int out_fd, int in_fd, off_t *_offset, size_t count) #endif /* ------------------------------- */ -static int ad_sendfile_init(const struct adouble *ad, +int ad_readfile_init(const struct adouble *ad, const int eid, off_t *off, const int end) { @@ -150,30 +128,16 @@ static int ad_sendfile_init(const struct adouble *ad, *off = ad_size(ad, eid) - *off; if (eid == ADEID_DFORK) { - fd = ad_dfileno(ad); + fd = ad_data_fileno(ad); } else { *off += ad_getentryoff(ad, eid); - fd = ad_hfileno(ad); + fd = ad_reso_fileno(ad); } return fd; } -/* -------------------------------- - * read from adouble file and write to socket. sendfile doesn't change - * the file pointer position. */ -ssize_t ad_readfile(const struct adouble *ad, const int eid, - const int sock, off_t off, const size_t len) -{ - off_t cc; - int fd; - - fd = ad_sendfile_init(ad, eid, &off, 0); - cc = sys_sendfile(sock, fd, &off, len); - return cc; -} - /* ------------------------ */ #if 0 #ifdef HAVE_SENDFILE_WRITE diff --git a/libatalk/dsi/dsi_stream.c b/libatalk/dsi/dsi_stream.c index f768e31f..2bd50bee 100644 --- a/libatalk/dsi/dsi_stream.c +++ b/libatalk/dsi/dsi_stream.c @@ -1,5 +1,5 @@ /* - * $Id: dsi_stream.c,v 1.17 2009-10-25 06:13:11 didg Exp $ + * $Id: dsi_stream.c,v 1.18 2009-10-25 09:47:05 didg Exp $ * * Copyright (c) 1998 Adrian Sun (asun@zoology.washington.edu) * All rights reserved. See COPYRIGHT. @@ -37,6 +37,7 @@ #include #include +#include #include #define min(a,b) ((a) < (b) ? (a) : (b)) @@ -191,6 +192,52 @@ ssize_t dsi_stream_write(DSI *dsi, void *data, const size_t length, int mode) return written; } + +/* --------------------------------- +*/ +ssize_t dsi_stream_read_file(DSI *dsi, int fromfd, off_t offset, const size_t length) +{ + size_t written; + ssize_t len; + + dsi->in_write++; + written = 0; + + while (written < length) { + len = sys_sendfile(dsi->socket, fromfd, &offset, length - written); + + if (len < 0) { + if (errno == EINTR) + continue; + if (errno == EINVAL || errno == ENOSYS) + return -1; + + if (errno == EAGAIN || errno == EWOULDBLOCK) { + if (dsi_buffer(dsi)) { + /* can't go back to blocking mode, exit, the next read + will return with an error and afpd will die. + */ + break; + } + continue; + } + LOG(log_error, logtype_default, "dsi_stream_write: %s", strerror(errno)); + break; + } + else if (!len) { + /* afpd is going to exit */ + errno = EIO; + return -1; /* I think we're at EOF here... */ + } + else + written += len; + } + + dsi->write_count += written; + dsi->in_write--; + return written; +} + /* --------------------------------- */ static size_t from_buf(DSI *dsi, u_int8_t *buf, size_t count)