From owner-freebsd-current@FreeBSD.ORG Sun Jul 31 14:20:20 2005 Return-Path: X-Original-To: freebsd-current@freebsd.org Delivered-To: freebsd-current@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 1453A16A41F for ; Sun, 31 Jul 2005 14:20:20 +0000 (GMT) (envelope-from keramida@freebsd.org) Received: from aiolos.otenet.gr (aiolos.otenet.gr [195.170.0.93]) by mx1.FreeBSD.org (Postfix) with ESMTP id 37C2343D45 for ; Sun, 31 Jul 2005 14:20:18 +0000 (GMT) (envelope-from keramida@freebsd.org) Received: from gothmog.gr (patr530-a128.otenet.gr [212.205.215.128]) by aiolos.otenet.gr (8.13.4/8.13.4/Debian-1) with ESMTP id j6VEI3oB027980 for ; Sun, 31 Jul 2005 17:18:03 +0300 Received: from gothmog.gr (gothmog [127.0.0.1]) by gothmog.gr (8.13.4/8.13.4) with ESMTP id j6VEI2E1049384 for ; Sun, 31 Jul 2005 17:18:02 +0300 (EEST) (envelope-from keramida@freebsd.org) Received: (from giorgos@localhost) by gothmog.gr (8.13.4/8.13.4/Submit) id j6VEI21s049383 for freebsd-current@freebsd.org; Sun, 31 Jul 2005 17:18:02 +0300 (EEST) (envelope-from keramida@freebsd.org) Date: Sun, 31 Jul 2005 17:18:01 +0300 From: Giorgos Keramidas To: freebsd-current@freebsd.org Message-ID: <20050731141801.GA49300@gothmog.gr> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Subject: mmap bug? X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 31 Jul 2005 14:20:20 -0000 The following program can be used to mmap() a region outside of the current size of a file and then write to it. Should this ``expand'' the current file size? If not, should writes on this area fail? What's more interesting is that after running it on -CURRENT, I can write data that is "attached" to the file but this doesn't affect the current size of the file. The test program I used was: # #include # #include # # #include # #include # #include # #include # #include # #include # # static int mmap_test(char *fname, size_t offset, size_t len); # static int mmap_dump(unsigned char *, size_t); # static int mmap_write_test(unsigned char *, size_t); # static void usage(void); # # int # main(int argc, char *argv[]) # { # char *fname, *errp; # long val; # size_t offset, len; # # if (argc != 4) # usage(); # # fname = argv[1]; # # errno = 0; # errp = NULL; # val = strtol(argv[2], &errp, 0); # if ((errp != NULL && *errp != '\0') || errno != 0) # err(1, "strtol: %s", argv[2]); # offset = (size_t)val; # # errno = 0; # errp = NULL; # val = strtol(argv[3], &errp, 0); # if ((errp != NULL && *errp != '\0') || errno != 0) # err(1, "strtol: %s", argv[3]); # len = (size_t)val; # # if (mmap_test(fname, offset, len) != 0) # exit(EXIT_FAILURE); # # return (0); # } # # static void # usage() # { # fprintf(stderr, "usage: foo file offset len\n"); # exit(EXIT_FAILURE); # } # # static int # mmap_test(char *fname, size_t offset, size_t len) # { # int fd; # void *ptr; # # fd = open(fname, O_CREAT | O_RDWR, S_IREAD | S_IWRITE); # if (fd == -1) # err(1, "open: %s", fname); # # ptr = mmap(NULL, len, PROT_READ | PROT_WRITE, # MAP_SHARED, fd, offset); # if (ptr == NULL) # err(1, "mmap"); # # mmap_dump((unsigned char *)ptr, len); # mmap_write_test((unsigned char *)ptr, len); # mmap_dump((unsigned char *)ptr, len); # # if (munmap(ptr, len) != 0) # err(1, "munmap"); # # close(fd); # return (0); # } # # static int # mmap_dump(unsigned char *p, size_t len) # { # size_t k; # # for (k = 0; k < len; k++) { # if ((k % 16) == 0) # printf("%08lx: ", (unsigned long)k); # printf(" %02x", p[k]); # if ((k % 16) == 15) # printf("\n"); # } # if ((k % 16) != 15) # printf("\n"); # return (0); # } # # static int # mmap_write_test(unsigned char *p, size_t len) # { # size_t k; # # for (k = 0; k < len; k++) # p[k] = (unsigned char)(k % 256); # return (0); # } Here's a sample run: # gothmog:/tmp/foo$ dd if=/dev/zero of=tempfile bs=512 count=10 # 10+0 records in # 10+0 records out # 5120 bytes transferred in 0.000575 secs (8903332 bytes/sec) # gothmog:/tmp/foo$ ls -l tempfile # -rw-rw-r-- 1 giorgos wheel - 5120 Jul 31 17:12 tempfile ok, the file has been created with the right size. # gothmog:/tmp/foo$ ./foo tempfile 5120 60 # 00000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 # 00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 # 00000020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 # 00000030: 00 00 00 00 00 00 00 00 00 00 00 00 # 00000000: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f # 00000010: 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f # 00000020: 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f # 00000030: 30 31 32 33 34 35 36 37 38 39 3a 3b mmap() succeeded and wrote after the previous end of the file. # gothmog:/tmp/foo$ ls -l tempfile # -rw-rw-r-- 1 giorgos wheel - 5120 Jul 31 17:12 tempfile # gothmog:/tmp/foo$ hd tempfile # 00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| # * # 00001400 The size of the file is still the same! # gothmog:/tmp/foo$ ./foo tempfile 5120 60 # 00000000: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f # 00000010: 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f # 00000020: 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f # 00000030: 30 31 32 33 34 35 36 37 38 39 3a 3b # 00000000: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f # 00000010: 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f # 00000020: 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f # 00000030: 30 31 32 33 34 35 36 37 38 39 3a 3b Somehow, the data written by the first mmap() is still there, but is not visible as part of the file size or by using ``normal'' commands that access its contents.