[master] e55924a Add a VFIL_allocate function
Martin Blix Grydeland
martin at varnish-software.com
Tue Oct 21 12:25:42 CEST 2014
commit e55924adaae8e647144c692d4ab4883437c93e75
Author: Martin Blix Grydeland <martin at varnish-software.com>
Date: Mon Oct 6 17:46:34 2014 +0200
Add a VFIL_allocate function
This function makes sure that the filesystem can accomodate the file
of the given size.
Checks the filesystem free space up against the allocated blocks as a
sanity check.
Uses fallocate if available to preallocate the needed blocks.
If fallocate isn't available, it will write zero bytes if insist is true.
diff --git a/configure.ac b/configure.ac
index e221fa7..a66d61a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -216,6 +216,7 @@ AC_CHECK_FUNCS([getdtablesize])
AC_CHECK_FUNCS([timegm])
AC_CHECK_FUNCS([nanosleep])
AC_CHECK_FUNCS([setppriv])
+AC_CHECK_FUNCS([fallocate])
save_LIBS="${LIBS}"
LIBS="${PTHREAD_LIBS}"
diff --git a/include/vfil.h b/include/vfil.h
index 32f2c78..dff6560 100644
--- a/include/vfil.h
+++ b/include/vfil.h
@@ -35,3 +35,4 @@ char *VFIL_readfile(const char *pfx, const char *fn, ssize_t *sz);
char *VFIL_readfd(int fd, ssize_t *sz);
int VFIL_nonblocking(int fd);
int VFIL_fsinfo(int fd, unsigned *pbs, uintmax_t *size, uintmax_t *space);
+int VFIL_allocate(int fd, off_t size, int insist);
diff --git a/lib/libvarnish/vfil.c b/lib/libvarnish/vfil.c
index b3743f2..d985e3e 100644
--- a/lib/libvarnish/vfil.c
+++ b/lib/libvarnish/vfil.c
@@ -39,6 +39,7 @@
#include <time.h>
#include <unistd.h>
#include <stdint.h>
+#include <string.h>
#include <sys/types.h>
#ifdef HAVE_SYS_MOUNT_H
# include <sys/param.h>
@@ -187,3 +188,55 @@ VFIL_fsinfo(int fd, unsigned *pbs, uintmax_t *psize, uintmax_t *pspace)
*pspace = space;
return (0);
}
+
+/* Make sure that the file system can accomodate the file of the given
+ * size. Will use fallocate if available. If fallocate is not available
+ * and insist is true, it will write size zero bytes.
+ *
+ * Returns 0 on success, -1 on failure with errno set.
+ */
+int
+VFIL_allocate(int fd, off_t size, int insist)
+{
+ struct stat st;
+ uintmax_t fsspace;
+ size_t l;
+ ssize_t l2;
+ char buf[64 * 1024];
+
+ if (ftruncate(fd, size))
+ return (-1);
+ if (fstat(fd, &st))
+ return (-1);
+ if (VFIL_fsinfo(fd, NULL, NULL, &fsspace))
+ return (-1);
+ if ((st.st_blocks * 512) + fsspace < size) {
+ /* Sum of currently allocated blocks and available space
+ is less than requested size */
+ errno = ENOSPC;
+ return (-1);
+ }
+#ifdef HAVE_FALLOCATE
+ if (!fallocate(fd, 0, 0, size))
+ return (0);
+ if (errno == ENOSPC)
+ return (-1);
+#endif
+ if (!insist)
+ return (0);
+
+ /* Write size zero bytes to make sure the entire file is allocated
+ in the file system */
+ memset(buf, 0, sizeof buf);
+ assert(lseek(fd, 0, SEEK_SET) == 0);
+ for (l = 0; l < size; l += l2) {
+ l2 = sizeof buf;
+ if (l + l2 > size)
+ l2 = size - l;
+ l2 = write(fd, buf, l2);
+ if (l2 < 0)
+ return (-1);
+ }
+ assert(lseek(fd, 0, SEEK_SET) == 0);
+ return (0);
+}
More information about the varnish-commit
mailing list