There seems to be something very odd in the handling of mmap'd files
which happen to reside on tmpfs filesystems.
I use temporary files to build up display lists which may be of
arbitrary size, and which periodically get emptied out again.
My first strategy was to create a file, make it 128Mb big, and map it.
On a ufs filesystem, everything works as it should - disc space is
only used up as I touch pages in the mapped address range, and I can
clear out the display list by truncating the file to 0 bytes, then
back up to 128Mb.
On tmpfs, two very strange things happen:
1) the pages appear to be allocated immediately I truncate the file
up, rather than when I first touch them.
2) I can't then truncate it back to zero bytes.
See the short program, blimey.c below. The current directory was on a
ufs filesystem with about 1.4Mb free, and I can happily truncate a
file up to 100,000,000 bytes. /tmp was on a tmpfs filesystem with
about 55Mb free.
This example was run on Solaris 2.3. I'm told the same thing happens
on 2.2, and at least part of the problem occurs on 2.1.
----------------------------------------------------------------------
Script started on Tue Nov 23 11:37:57 1993
ipc% cat blimey.c
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/param.h>
#include <stdio.h>
#include <fcntl.h>
main (int argc, char **argv)
{
int fd;
caddr_t val;
char cmd[MAXPATHLEN + 16];
int bytes;
int j;
if (argc != 3) {
fprintf (stderr, "Usage: blimey filename bytes\n");
exit (1);
}
bytes = atoi (argv[2]);
if (bytes == 0) {
fprintf (stderr, "Usage: blimey filename bytes\n");
exit (1);
}
fd = open (argv[1], O_RDWR | O_CREAT | O_TRUNC, 0666);
if (fd < 0) {
perror ("open");
exit (1);
}
printf ("Opened %s OK\n", argv[1]);
sprintf (cmd, "ls -l %s", argv[1]);
printf (" %% %s\n", cmd);
system (cmd);
printf ("\n");
if (ftruncate (fd, bytes) < 0) {
perror ("ftruncate");
exit (1);
}
printf ("Truncated %s OK\n", argv[1]);
system (cmd);
printf ("\n");
val = mmap (0, bytes,
PROT_READ | PROT_WRITE,
MAP_SHARED,
fd, 0);
if (val == (caddr_t) -1) {
perror ("mmap");
exit (1);
}
printf ("Mapped %s OK\n", argv[1]);
system (cmd);
printf ("\n");
for (j = 0; j < 100; j++) {
((char *) val)[rand() % bytes] = 0;
}
if (ftruncate (fd, 0) < 0) {
perror ("ftruncate");
exit (1);
}
printf ("Truncated %s OK\n", argv[1]);
system (cmd);
printf ("\n");
close (fd);
if (unlink (argv[1]) < 0) {
perror ("unlink");
exit (1);
}
printf ("Unlinked %s OK\n", argv[1]);
system (cmd);
printf ("\n");
exit (0);
ipc% blimey foo 10000Quote:}
Opened foo OK
% ls -l foo
-rw-r--r-- 1 ian staff 0 Nov 23 11:38 foo
Truncated foo OK
-rw-r--r-- 1 ian staff 10000 Nov 23 11:38 foo
Mapped foo OK
-rw-r--r-- 1 ian staff 10000 Nov 23 11:38 foo
Truncated foo OK
-rw-r--r-- 1 ian staff 0 Nov 23 11:38 foo
Unlinked foo OK
foo: No such file or directory
ipc% blimey /tmp/foo 10000
Opened /tmp/foo OK
% ls -l /tmp/foo
-rw-r--r-- 1 ian staff 0 Nov 23 11:38 /tmp/foo
Truncated /tmp/foo OK
-rw-r--r-- 1 ian staff 10000 Nov 23 11:38 /tmp/foo
Mapped /tmp/foo OK
-rw-r--r-- 1 ian staff 10000 Nov 23 11:38 /tmp/foo
ftruncate: Device busy
ipc% blimey foo 100000000
Opened foo OK
% ls -l foo
-rw-r--r-- 1 ian staff 0 Nov 23 11:38 foo
Truncated foo OK
-rw-r--r-- 1 ian staff 100000000 Nov 23 11:38 foo
Mapped foo OK
-rw-r--r-- 1 ian staff 100000000 Nov 23 11:38 foo
Truncated foo OK
-rw-r--r-- 1 ian staff 0 Nov 23 11:38 foo
Unlinked foo OK
foo: No such file or directory
ipc% blimey /tmp/foo 100000000
Opened /tmp/foo OK
% ls -l /tmp/foo
-rw-r--r-- 1 ian staff 0 Nov 23 11:38 /tmp/foo
ftruncate: No space left on device
ipc% exit
ipc%
script done on Tue Nov 23 11:39:02 1993
----------------------------------------------------------------------
My problem is that the location of my temporary files is up to the OEM
and/or end user. There are significant advantages to mapping the
temporary files, but at the moment I can't do this, because there are
people out there who are in the habit of putting them on tmpfs
filesystems.
Help! Because of this problem, at the moment, the most advanced
version of my stuff is the one that runs on Windows NT. Help me avoid
the shame of it! Are there any workarounds?
--
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Ian Kemmish 18 Durham Close, Biggleswade, Beds SG18 8HZ
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -