Re: 2.4.0-test10-pre3:Oops in mm/filemap.c:filemap_write_pa

From: Petr Vandrovec (VANDROVE@vc.cvut.cz)
Date: Mon Oct 23 2000 - 14:40:28 EST


On 23 Oct 00 at 12:09, Linus Torvalds wrote:
> On Mon, 23 Oct 2000, Petr Vandrovec wrote:
> >
> > Hi Linus,
> > unfortunately, this does not explain problem I reported. In my case,
> > underlying fs is ext2, and there is no locking around - only one task
> > does ftruncate() on (big) shareable mapped file (original code does it to
> > prevent dirty pages to be written to disk after their contents is no
> > longer relevant).
>
> Yes. Yours is a separate problem, and is not due to invalidate_pages() at
> all, but apparently due to truncate_complete_page().
>
> Basically, all the same old arguments do apply - we cannot just remove the
> page from the page cache if it is mapped.
>
> Now, the truncate() case is different, because the code _tries_ to also
> zap the actual mappings. The fact that it fails to do so is a bit
> unnerving, actually.
>
> I'll take a better look at the truncate case (I consider the invalidate
> case closed). Do you have a simple test-program around?

Well, I cannot say simple. As I was not able to reproduce it with only
one task, code below:
(1) mlocks itself in memory (you can remove it)
(2) creates 224MB file and maps it shareable into memory (224 is
    for 256MB machine; I was not able to reproduce it with less than 100MB
    file on 256MB machine) (and you must have 224MB of free disk space
    in current directory, otherwise...) and unlinks it
(3) fork
(4) child process dirties memory
(5) parent signals child to exit and wait 5 secs
(6) child exits (hopefully...)
(7) parent unmaps data
(8) parent exits
You'll always get page->mapping == NULL dereference... And btw, if
I start code below on my machine (dual PIII/450), after 2 secs of run
whole machine stops - only ping and console switching works - and stays
that way for more than 20 secs. After that program finishes (killing
kernel if no antioops in filemap_write_page present...) and everything
returns to normal (if "-/+ buffers/cache: 28848 226920" is normal ;-) ).

  You can look at "http://platan.vc.cvut.cz/listit" for dump of "struct page"
at time when page->mapping == NULL was catched in filemap_write_page,
or through linux-kernel@ archive searching for 'page->mapping == NULL'
during last month, either from me or from Quintella.
                                                Thanks,
                                                    Petr Vandrovec
                                                    vandrove@vc.cvut.cz
                                                    

#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <sys/ioctl.h>
#include <sys/raw.h>

unsigned char zero;

#define MSIZE 0x0E000000

void x4768(void) {
    int fd;
    pid_t pid;
    int x4778_1[2];
    int x4778_2[2];
    int from4778;
    int to4778;
    char* mma[65536];
    unsigned int mml[65536];
    unsigned int mmi = 0;
    unsigned int ln = 0;
    unsigned int x;
    
#define MAL2(a,l) ftruncate(fd, ln+l); mml[mmi] = l; mma[mmi++] = mmap(a, l, PROT_READ|PROT_WRITE, MAP_SHARED, fd, ln); ln += l; mma[mmi-1][0] = 99;
#define MAL(l) MAL2(NULL,l)

    fd = open("ram0", O_RDWR | O_CREAT, 0600);
    unlink("ram0");
    MAL(MSIZE);
    pipe(x4778_1);
    pipe(x4778_2);
    pid = fork();
    if (!pid) {
        int from4768 = x4778_1[0];
        int to4768 = x4778_2[1];
        close(x4778_1[1]);
        close(x4778_2[0]);
        close(fd);
        read(from4768, &zero, 1);
        for (x = 0; x < mml[mmi - 1]; x += 4096)
            mma[mmi-1][x] = 98;
        write(to4768, &zero, 1);
        read(from4768, &zero, 1);
        exit(0);
        
    } else if (pid < 0) {
        perror("fork failed");
        exit(222);
    }
    to4778 = x4778_1[1];
    from4778 = x4778_2[0];
    close(x4778_1[0]);
    close(x4778_2[1]);

    {
        write(to4778, &zero, 1);
        read(from4778, &zero, 1);

        write(to4778, &zero, 1);
        sleep(5);
        ftruncate(fd, 0);
    }
    while (mmi--) {
        munmap(mma[mmi], mml[mmi]);
    }
    exit(0);
}

int main(int argc, char* argv[]) {
    printf("Go\n");
    mlockall(MCL_CURRENT);
    
    x4768();
    return 0;
}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Mon Oct 23 2000 - 21:00:21 EST