aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/drivers/common
diff options
context:
space:
mode:
authorFilipe David Manana <[email protected]>2010-12-28 10:57:04 +0000
committerBjörn-Egil Dahlberg <[email protected]>2013-01-09 18:15:02 +0100
commitc48348233c467f7dc96728a31710abbb12cbe1f1 (patch)
tree61799089ba9052042ead12755a36b5bb818884ba /erts/emulator/drivers/common
parent9229901660ef1c163ea82c76ea3dc21f5a4f83d4 (diff)
downloadotp-c48348233c467f7dc96728a31710abbb12cbe1f1.tar.gz
otp-c48348233c467f7dc96728a31710abbb12cbe1f1.tar.bz2
otp-c48348233c467f7dc96728a31710abbb12cbe1f1.zip
Add file:allocate/3 operation
This operation allows pre-allocation of space for files. It succeeds only on systems that support such operation. The POSIX standard defines the optional system call posix_fallocate() to implement this feature. However, some systems implement more specific functions to accomplish the same operation. On Linux, if the more specific function fallocate() is implemented, it is used instead of posix_fallocate(), falling back to posix_fallocate() if the fallocate() call failed (it's only supported for the ext4, ocfs2, xfs and btrfs file systems at the moment). On Mac OS X it uses the specific fcntl() operation F_PREALLOCATE, falling back to posix_fallocate() if it's available (at the moment Mac OS X doesn't provide posix_fallocate()). On any other UNIX system, it uses posix_fallocate() if it's available. Any other system not providing this system call or any function to pre-allocate space for files, this operation always fails with the ENOTSUP POSIX error.
Diffstat (limited to 'erts/emulator/drivers/common')
-rw-r--r--erts/emulator/drivers/common/efile_drv.c31
-rw-r--r--erts/emulator/drivers/common/erl_efile.h1
-rw-r--r--erts/emulator/drivers/common/ram_file_drv.c8
3 files changed, 40 insertions, 0 deletions
diff --git a/erts/emulator/drivers/common/efile_drv.c b/erts/emulator/drivers/common/efile_drv.c
index 912f5d3d8b..2c38e7256a 100644
--- a/erts/emulator/drivers/common/efile_drv.c
+++ b/erts/emulator/drivers/common/efile_drv.c
@@ -56,6 +56,7 @@
#define FILE_FDATASYNC 30
#define FILE_FADVISE 31
#define FILE_SENDFILE 32
+#define FILE_FALLOCATE 33
/* Return codes */
@@ -503,6 +504,10 @@ struct t_data
Uint64 written;
} sendfile;
#endif /* HAVE_SENDFILE */
+ struct {
+ Sint64 offset;
+ Sint64 length;
+ } fallocate;
} c;
char b[1];
};
@@ -1953,6 +1958,17 @@ static int flush_sendfile(file_descriptor *desc,void *_) {
#endif /* HAVE_SENDFILE */
+static void invoke_fallocate(void *data)
+{
+ struct t_data *d = (struct t_data *) data;
+ int fd = (int) d->fd;
+ Sint64 offset = d->c.fallocate.offset;
+ Sint64 length = d->c.fallocate.length;
+
+ d->again = 0;
+ d->result_ok = efile_fallocate(&d->errInfo, fd, offset, length);
+}
+
static void free_readdir(void *data)
{
struct t_data *d = (struct t_data *) data;
@@ -2348,6 +2364,7 @@ file_async_ready(ErlDrvData e, ErlDrvThreadData data)
case FILE_RENAME:
case FILE_WRITE_INFO:
case FILE_FADVISE:
+ case FILE_FALLOCATE:
reply(desc, d->result_ok, &d->errInfo);
free_data(data);
break;
@@ -2958,6 +2975,20 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count)
goto done;
}
+ case FILE_FALLOCATE:
+ {
+ d = EF_SAFE_ALLOC(sizeof(struct t_data));
+
+ d->fd = fd;
+ d->command = command;
+ d->invoke = invoke_fallocate;
+ d->free = free_data;
+ d->level = 2;
+ d->c.fallocate.offset = get_int64((uchar*) buf);
+ d->c.fallocate.length = get_int64(((uchar*) buf) + sizeof(Sint64));
+ goto done;
+ }
+
}
/*
diff --git a/erts/emulator/drivers/common/erl_efile.h b/erts/emulator/drivers/common/erl_efile.h
index 69ad02633c..b29b4f971c 100644
--- a/erts/emulator/drivers/common/erl_efile.h
+++ b/erts/emulator/drivers/common/erl_efile.h
@@ -185,3 +185,4 @@ int efile_fadvise(Efile_error* errInfo, int fd, Sint64 offset, Sint64 length,
int efile_sendfile(Efile_error* errInfo, int in_fd, int out_fd,
off_t *offset, Uint64 *nbytes, struct t_sendfile_hdtl *hdtl);
#endif /* HAVE_SENDFILE */
+int efile_fallocate(Efile_error* errInfo, int fd, Sint64 offset, Sint64 length);
diff --git a/erts/emulator/drivers/common/ram_file_drv.c b/erts/emulator/drivers/common/ram_file_drv.c
index a109e40333..7f7cd7cd91 100644
--- a/erts/emulator/drivers/common/ram_file_drv.c
+++ b/erts/emulator/drivers/common/ram_file_drv.c
@@ -48,6 +48,7 @@
#define RAM_FILE_SIZE 37 /* get file size */
#define RAM_FILE_ADVISE 38 /* predeclare the access
* pattern for file data */
+#define RAM_FILE_ALLOCATE 39 /* allocate space for a file */
/* possible new operations include:
DES_ENCRYPT
DES_DECRYPT
@@ -720,6 +721,13 @@ static void rfile_command(ErlDrvData e, char* buf, ErlDrvSizeT count)
else
reply(f, 1, 0);
break;
+
+ case RAM_FILE_ALLOCATE:
+ if (f->flags == 0)
+ error_reply(f, EBADF);
+ else
+ reply(f, 1, 0);
+ break;
}
/*
* Ignore anything else -- let the caller hang.