[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