[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

jffs out of space for no obvious reason

Hi all,

Sébastien suggested last week that I post this here,
as I've run into a jffs bug which no one else seems
to have hit. Apologies for the long post. I've tried
to include enough info for someone else to duplicate
the problem.

btw, this was with a source snapshot from the MTD
site aprx July 3. I was using mtdram for testing, so
I can't rule out that this is actually an MTD bug.

Anyway, here's the basic situation. You open a new
file read/write, then seek to some position and write
a byte. Then loop seeking to random places in the
middle of the file and writing random amounts of data,
never going off the end established by the first write.
All you're doing here is writing into the middle of
a fixed size file which never grows. After a while
write() returns with an out of space error. ls -l shows
the file of the size you created with the first write,
and df shows a negative amount of available space.

The same result occurs if the file is initially created
by writing occasional byte from start to the desired
end point.

Here are some code extracts to illustrate the file

--------------create file------

char *
make_file(fdp, fsp, max_size)
    int    *fdp;                // Points to fd value we provide caller
    size_t *fsp,                // Points to actual file size
            max_size;           // Variable size file size limit, fixed if 0
    char  *errmsg = NULL;       // Error message we return, be optimistic
    int    fd;                  // Open fd for file we create
    size_t file_size = *fsp;    // Working copy of file size

    if (max_size)               // Establish file size and name
        file_size = max_size * (long long) random() / RAND_MAX;
    sprintf(fname, "%s/%s%-X", dirname, name, getpid());

    if ((fd = open(fname, O_RDWR | O_CREAT | O_EXCL | oflags, 0600)) < 0)
        errmsg = strcat(fname, " open");   // oflags is usually O_SYNC

    else {
        off_t posn = fill_holes ? 0 : file_size - 1;

        do {
            if (lseek(fd, posn, SEEK_SET) != posn || write(fd, "", 1) != 1)
                errmsg = strcat(fname, fill_holes ? " filling" : " sizing");

        } while (errmsg == NULL && (posn += 512) < file_size);

    *fsp = file_size;           // Pass final file size back to caller
    *fdp = errmsg ? -1 : fd;    // Pass fd to caller

    return errmsg;

After the program calls make file it sits in the following loop:

----------writing the file----------

    if (fd >= 0) {              // Run test loop if we've got an open file
        char *bfr = malloc(file_size);

        while(errmsg == NULL) {
           /* We're going to write random size chunks from the start of
            * bfr to random locations in the file.
            * Require 0 <= posn <  file_size.
            * Require 0 <= bc   <= file_size.
           off_t  posn = (file_size - 1) * (long long) random() / RAND_MAX;
           size_t bc   = file_size * (long long) random() / RAND_MAX;

           if ((posn + bc) > file_size)     // Don't write past the end!
               bc = file_size - posn;

           if (lseek(fd, posn, SEEK_SET) != posn)
               errmsg = strcat(fname, " seek");

           else if (write(fd, bfr, bc) != bc) 
               errmsg = strcat(fname, " write");

           else if (use_fsync && fsync(fd))
               errmsg = strcat(fname, " fsync");

Here's a session showing the results:

[root@BorgGates nvrblk]# mount /dev/mtdblk /mnt/jffs
[root@BorgGates nvrblk]# ls -l /mnt/jffs
total 0
[root@BorgGates nvrblk]# df /mnt/jffs
Filesystem           1k-blocks      Used Available Use% Mounted on
/dev/mtdblk               1952         0      1952   0% /mnt/jffs
[root@xxxxxxx./writer -d /mnt/jffs -n 1
writer: /mnt/jffs/writer8B6 write failed -- No space left on device.
[root@BorgGates nvrblk]# ls -l /mnt/jffs
total 0
-rw-------   1 root     root         1024 Jul  4 18:29 writer8B6
[root@BorgGates nvrblk]# df /mnt/jffs
Filesystem           1k-blocks      Used Available Use% Mounted on
/dev/mtdblk               1952         - 17179869180   -  /mnt/jffs
[root@BorgGates nvrblk]# umount /mnt/jffs
[root@BorgGates nvrblk]# mount /dev/mtdblk /mnt/jffs
[root@BorgGates nvrblk]# ls -l /mnt/jffs
total 0
-rw-------   1 root     root      1695940 Jul  4 18:29 writer8B6
[root@BorgGates nvrblk]# df /mnt/jffs
Filesystem           1k-blocks      Used Available Use% Mounted on
/dev/mtdblk               1952         - 17179869180   -  /mnt/jffs
[root@BorgGates nvrblk]# 

Has anyone else seen this sort of thing? It almost acts like space
which should be made available for later reuse when nodes get
rewritten are being lost somehow.