diff options
| author | Sebastian Andrzej Siewior <sebastian@breakpoint.cc> | 2014-01-18 21:24:58 +0100 | 
|---|---|---|
| committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2014-01-19 15:08:49 +0100 | 
| commit | d3581b58890389794de5d5222c91a0129873e95c (patch) | |
| tree | 95c4010b61869934cca86c5ac23056463754f2ee | |
| parent | ea7210bef377be4ffb088a1a8e5a9dd354f82afb (diff) | |
cache: use sendfile() instead of a pair of read() + write()
sendfile() does the same job and avoids to copy the content into userland
and back. One has to define NO_SENDFILE in case the OS (kernel / libc)
does not supported. It is disabled by default on non-linux environemnts.
According to the glibc, sendfile64() was added in Linux 2.4 (so it has
been there for a while) but after browsing over the mapage of FreeBSD's I
noticed that the prototype is little different.
Signed-off-by: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
| -rw-r--r-- | Makefile | 1 | ||||
| -rw-r--r-- | cache.c | 26 | ||||
| -rw-r--r-- | cgit.mk | 8 | 
3 files changed, 34 insertions, 1 deletions
| @@ -29,6 +29,7 @@ DOC_PDF  = $(patsubst %.txt,%.pdf,$(MAN_TXT))  # j, z, t. (representing long long int, char, intmax_t, size_t, ptrdiff_t).  # some C compilers supported these specifiers prior to C99 as an extension.  # +# Define HAVE_LINUX_SENDFILE to use sendfile()  #-include config.mak @@ -13,6 +13,9 @@   *   */ +#ifdef HAVE_LINUX_SENDFILE +#include <sys/sendfile.h> +#endif  #include "cgit.h"  #include "cache.h"  #include "html.h" @@ -30,7 +33,6 @@ struct cache_slot {  	const char *lock_name;  	int match;  	struct stat cache_st; -	struct stat lock_st;  	int bufsize;  	char buf[CACHE_BUFSIZE];  }; @@ -81,6 +83,23 @@ static int close_slot(struct cache_slot *slot)  /* Print the content of the active cache slot (but skip the key). */  static int print_slot(struct cache_slot *slot)  { +#ifdef HAVE_LINUX_SENDFILE +	off_t start_off; +	int ret; + +	start_off = slot->keylen + 1; + +	do { +		ret = sendfile(STDOUT_FILENO, slot->cache_fd, &start_off, +				slot->cache_st.st_size - start_off); +		if (ret < 0) { +			if (errno == EAGAIN || errno == EINTR) +				continue; +			return errno; +		} +		return 0; +	} while (1); +#else  	ssize_t i, j;  	i = lseek(slot->cache_fd, slot->keylen + 1, SEEK_SET); @@ -97,6 +116,7 @@ static int print_slot(struct cache_slot *slot)  		return errno;  	else  		return 0; +#endif  }  /* Check if the slot has expired */ @@ -188,6 +208,10 @@ static int fill_slot(struct cache_slot *slot)  	/* Generate cache content */  	slot->fn(); +	/* update stat info */ +	if (fstat(slot->lock_fd, &slot->cache_st)) +		return errno; +  	/* Restore stdout */  	if (dup2(tmp, STDOUT_FILENO) == -1)  		return errno; @@ -68,6 +68,14 @@ ifeq ($(findstring BSD,$(uname_S)),)  	CGIT_LIBS += -ldl  endif +# glibc 2.1+ offers sendfile which the most common C library on Linux +ifeq ($(uname_S),Linux) +	HAVE_LINUX_SENDFILE = YesPlease +endif + +ifdef HAVE_LINUX_SENDFILE +	CGIT_CFLAGS += -DHAVE_LINUX_SENDFILE +endif  CGIT_OBJ_NAMES += cgit.o  CGIT_OBJ_NAMES += cache.o | 
