Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 4 Apr 1998 17:23:20 -0800 (PST)
From:      Matthew Dillon <dillon@backplane.com>
To:        FreeBSD-gnats-submit@FreeBSD.ORG
Subject:   kern/6212: MFS msync bug, MFS-related pager bug (with fixes)
Message-ID:  <199804050123.RAA07844@apollo.backplane.com>

next in thread | raw e-mail | index | archive | help

>Number:         6212
>Category:       kern
>Synopsis:       Two bugs with MFS filesystems fixed, one feature added
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:
>Keywords:
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sat Apr  4 17:30:01 PST 1998
>Last-Modified:
>Originator:     Matthew Dillon
>Organization:
Best Internet Communications
>Release:        FreeBSD 3.0-CURRENT i386
>Environment:

	Pentium based diskless FreeBSD box.

>Description:

	The kernel does not set the P_SYSTEM flag for the MFS filesystem
	processes.  Due to the size of the processes this will result
	in the kernel attempting to kill the process over and over again
	if it runs out of swap, which really screws the machine up.
	(note: my one-liner fix to this is probably not in the right place)

	The MFS kernel process needs to msync() the memory map to backing
	store (which only effects MFS mounts that use a file for backing store).
	If it fails to do so, the kernel syncer will *never* *see* the dirty
	pages.  (note:  I change the tsleep() to tsleep() with a timeout and
	check the time, calling msync() every 30 seconds).

	The mount_mfs program (the mkfs.c code) insists on clearing the 
	backing store file if one has been specified.   There are lots of
	people who probably would like to be able to use an NFS mounted file
	for backing store, and this clearing results in a massive amount
	of network I/O (especially if you are mounting huge filesystems).
	Also included in my bug fixes is a modification to the program to
	check the size of the file and only truncate/pre-initialize it
	if it does not match the size of the requested filesystem.  If it
	does match, mount_mfs does not bother to clear it and simply
	newfs's over whatever data was previously there.

>How-To-Repeat:

	

>Fix:
	

Index: mfs_vfsops.c
===================================================================
RCS file: /src/FreeBSD-CVS/ncvs/src/sys/ufs/mfs/mfs_vfsops.c,v
retrieving revision 1.41
diff -r1.41 mfs_vfsops.c
48a49,50
> #include <sys/sysproto.h>	/* for msync_args */
> #include <sys/mman.h>	/* for msync_args */
432a435,441
> 	/*
> 	 * must mark the calling process as a system process
> 	 * so the pager doesn't try to kill it.  Doh!  And the
> 	 * pager may because the resident set size may be huge.
> 	 */
> 	p->p_flag |= P_SYSTEM;
> 
483c492
< 		else if (tsleep((caddr_t)vp, mfs_pri, "mfsidl", 0))
---
> 		else if (tsleep((caddr_t)vp, mfs_pri, "mfsidl", hz * 10))
484a494,518
> 
> 		/*
> 		 * we should call msync on the backing store every 30 seconds,
> 		 * otherwise the pages are not associated with the file and guess
> 		 * what!  the syncer never sees them.  msync has no effect 
> 		 * if the backing store is swap, but a big effect if it's a file
> 		 * (e.g. an NFS mounted file).
> 		 */
> 		{
> 			static long lsec;
> 			int dt = time_second - lsec;
> 
> 			if (dt < -30 || dt > 30) {
> 				struct msync_args uap;
> 
> 				lsec = time_second;
> 
> 				uap.addr = mfsp->mfs_baseoff;
> 				uap.len = mfsp->mfs_size;
> 				uap.flags = MS_ASYNC;
> 
> 				msync(curproc, &uap);
> 			}
> 		}
> 
Index: mkfs.c
===================================================================
RCS file: /src/FreeBSD-CVS/ncvs/src/sbin/newfs/mkfs.c,v
retrieving revision 1.20
diff -r1.20 mkfs.c
42a43
> #include <sys/stat.h>
181c182,184
< 			fd = open(filename,O_RDWR|O_TRUNC|O_CREAT,0644);
---
> 			struct stat st;
> 
> 			fd = open(filename,O_RDWR|O_CREAT,0644);
186,193c189,200
< 			for(l=0;l< fssize * sectorsize;l += l1) {
< 				l1 = fssize * sectorsize;
< 				if (BUFSIZ < l1)
< 					l1 = BUFSIZ;
< 				if (l1 != write(fd,buf,l1)) {
< 					perror(filename);
< 					exit(12);
< 				}
---
> 			fstat(fd, &st);
> 			if (st.st_size != fssize * sectorsize) {
> 			    ftruncate(fd, fssize * sectorsize);
> 			    for(l=0;l< fssize * sectorsize;l += l1) {
> 				    l1 = fssize * sectorsize;
> 				    if (BUFSIZ < l1)
> 					    l1 = BUFSIZ;
> 				    if (l1 != write(fd,buf,l1)) {
> 					    perror(filename);
> 					    exit(12);
> 				    }
> 			    }


>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199804050123.RAA07844>