Subject: Re: VI is crazy !!!
To: Joao Carlos Mendes Luis <jonny@gaia.coppe.ufrj.br>
From: Greg Hudson <ghudson@mit.edu>
List: netbsd-help
Date: 03/01/1996 01:04:08
> If I edit an existing file, add a new line in the middle, and save
> it, the saved file will be corrupted.  The *exact* number os
> characters added will be added to the file a ^@ (ascii 0) at the end
> of the file, but all the remaining text is still unchanged.

The problem here is that vi memory-maps the files it edits, so the
file is loaded in through the virtual memory cache.  NetBSD does not
keep its virtual memory cache in sync with the filesystem at all
times, so sometimes the VM cache can get out of date.  Thus, even when
the file looks fine to "od" or "cat" or to the ":r" command in vi, it
still looks out of date in vi (and with a bunch of ASCII 0s at the end
if the file grows).

We in the operating circles like to refer to this as a "bug."

One workaround is to flush your VM cache ("cat /sbin/* /bin/* >
/dev/null").

Fixing the NetBSD VM problem is hard, but I believe you can fix the vi
bug with the following patch (which I haven't tested very conclusively
yet):

*** lib/libc/db/recno/rec_open.c	1995/10/30 23:40:20	1.1
--- lib/libc/db/recno/rec_open.c	1995/10/30 23:40:45
***************
*** 170,175 ****
--- 170,176 ----
  				    PROT_READ, MAP_PRIVATE, rfd,
  				    (off_t)0)) == (caddr_t)-1)
  					goto slow;
+ 				msync(t->bt_smap, t->bt_msize);
  				t->bt_cmap = t->bt_smap;
  				t->bt_emap = t->bt_smap + sb.st_size;
  				t->bt_irec = ISSET(t, R_FIXLEN) ?
*** usr.bin/vi/ex/ex_tag.c	1995/10/30 23:41:01	1.1
--- usr.bin/vi/ex/ex_tag.c	1995/10/30 23:41:20
***************
*** 762,767 ****
--- 762,768 ----
  		(void)close(fd);
  		return (1);
  	}
+ 	msync(map, (size_t)sb.st_size);
  	front = map;
  	back = front + sb.st_size;
  
[Note for developers: I don't recommend committing this patch to the
mainline.  Instead, the kernel should be modified to do the equivalent
of an msync() after every mmap(), until we have a VM with merged
caches; this shouldn't be a difficult change.  Or (slightly harder)
the buffer cache should be taught to invalidate appropriate pages in
the VM cache.]