Re: bus error when disk is full, with mmap & sparse file
Richard Laager <[email protected]> Wed, 01 Feb 2012 23:35:16 -0600
| Newsgroups | gmane.comp.db.rrdtool.devel |
|---|---|
| Message-ID | <1328160916.3572.5.camel__30311.9817785502$1328160962$gmane$org@watermelon.coderich.net> |
I stumbled across this thread: http://permalink.gmane.org/gmane.comp.db.rrdtool.devel/4102 I've attached a patch that uses fallocate(), which may address this issue. Also, it should be faster than filling the file with zeros from userspace and may also decrease file fragmentation. I've only lightly tested the patch. Sorry my reply isn't threaded properly. I couldn't find an mbox-format archive to use for replying. -- Richard _______________________________________________ rrd-developers mailing list [email protected] https://lists.oetiker.ch/cgi-bin/listinfo/rrd-developers
rrdtool-fallocate.patch
(text/x-patch, 3 KB)
Index: src/rrd_open.c
===================================================================
--- src/rrd_open.c (revision 2268)
+++ src/rrd_open.c (working copy)
@@ -15,6 +15,9 @@
#include <sys/stat.h>
#endif
+#ifdef HAVE_FALLOCATE
+#include <fcntl.h>
+#endif
#ifdef HAVE_BROKEN_MS_ASYNC
#include <sys/types.h>
@@ -104,7 +107,10 @@
#ifdef HAVE_MMAP
ssize_t _page_size = sysconf(_SC_PAGESIZE);
char *data = MAP_FAILED;
+#ifdef HAVE_FALLOCATE
+ int allocated = 0;
#endif
+#endif
off_t offset = 0;
struct stat statb;
rrd_file_t *rrd_file = NULL;
@@ -221,13 +227,34 @@
if (newfile_size == 0) {
rrd_file->file_len = statb.st_size;
} else {
+#ifdef HAVE_FALLOCATE
+ int err;
+#endif
rrd_file->file_len = newfile_size;
- lseek(rrd_simple_file->fd, newfile_size - 1, SEEK_SET);
- if ( write(rrd_simple_file->fd, "\0", 1) == -1){ /* poke */
- rrd_set_error("write '%s': %s", file_name, rrd_strerror(errno));
- goto out_close;
+#ifdef HAVE_FALLOCATE
+ err = fallocate(rrd_simple_file->fd, 0, 0, newfile_size);
+#ifdef HAVE_MMAP
+ if (err == 0) {
+ allocated = 1;
+ } else {
+#else
+ if (err == -1) {
+#endif
+ if (errno != EOPNOTSUPP) {
+ rrd_set_error("fallocate '%s': %s", file_name,
+ rrd_strerror(errno));
+ goto out_close;
+ }
+#endif
+ lseek(rrd_simple_file->fd, newfile_size - 1, SEEK_SET);
+ if ( write(rrd_simple_file->fd, "\0", 1) == -1){ /* poke */
+ rrd_set_error("write '%s': %s", file_name, rrd_strerror(errno));
+ goto out_close;
+ }
+ lseek(rrd_simple_file->fd, 0, SEEK_SET);
+#ifdef HAVE_FALLOCATE
}
- lseek(rrd_simple_file->fd, 0, SEEK_SET);
+#endif
}
#ifdef HAVE_POSIX_FADVISE
/* In general we need no read-ahead when dealing with rrd_files.
@@ -254,7 +281,11 @@
* mapping can also lead some bus error, so we use the old fashioned
* write().
*/
+#ifdef HAVE_FALLOCATE
+ if (rdwr & RRD_CREAT && !allocated) {
+#else
if (rdwr & RRD_CREAT) {
+#endif
char buf[4096];
unsigned i;
@@ -263,7 +294,7 @@
for (i = 0; i < (newfile_size - 1) / sizeof buf; ++i)
{
- if (write(rrd_simple_file->fd, buf, sizeof buf) == -1)
+ if (write(rrd_simple_file->fd, buf, sizeof buf) == -1)
{
rrd_set_error("write '%s': %s", file_name, rrd_strerror(errno));
goto out_close;
Index: configure.ac
===================================================================
--- configure.ac (revision 2268)
+++ configure.ac (working copy)
@@ -225,6 +225,8 @@
CONFIGURE_PART(Map/Fadvis/Madvise checking)
+AC_CHECK_FUNCS(fallocate)
+
dnl Could use these to know if we need to provide a prototype
dnl AC_CHECK_DECLS(fdatasync, [], [], [#include <unistd.h>])
signature.asc
(application/pgp-signature, 198 B)
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iEYEABECAAYFAk8qIIMACgkQbfU6uV4fG84zcQCg0uB03Xf82zyd2Br2OxB/sSlS q8kAoOkssUjEvVdzOT8E2swfO4vG83sX =GvGx -----END PGP SIGNATURE-----