mfc linux_stats.c:1.86 to releng_6 - fifoor fix

John E Hein jhein at timing.com
Tue Jun 3 19:21:23 UTC 2008


Can someone MFC to 6.x Junk-uk Kim's fix for the linux block-on-a-fifo
problem (rev 1.86 of linux_stats.c)?

I've been running with it for nearly two years now without a problem.
It's already in RELENG_7.

I prepared a patch against RELENG_6 to make it easier...


Index: sys/compat/linux/linux_stats.c
===================================================================
RCS file: /base/FreeBSD-CVS/src/sys/compat/linux/linux_stats.c,v
retrieving revision 1.72.2.8
diff -u -p -r1.72.2.8 linux_stats.c
--- sys/compat/linux/linux_stats.c	9 Jan 2008 16:07:32 -0000	1.72.2.8
+++ sys/compat/linux/linux_stats.c	3 Jun 2008 15:57:55 -0000
@@ -99,23 +99,16 @@ static void
 translate_fd_major_minor(struct thread *td, int fd, struct stat *buf)
 {
 	struct file *fp;
-	int error;
 	int major, minor;
 
-	if ((error = fget(td, fd, &fp)) != 0)
+	if ((!S_ISCHR(buf->st_mode) && !S_ISBLK(buf->st_mode)) ||
+	    fget(td, fd, &fp) != 0)
 		return;
-	if (fp->f_vnode) {
-		if (fp->f_vnode->v_type == VCHR
-		    || fp->f_vnode->v_type == VBLK) {
-			if (fp->f_vnode->v_un.vu_cdev) {
-				if (linux_driver_get_major_minor(
-				    fp->f_vnode->v_un.vu_cdev->si_name,
-				    &major, &minor) == 0) {
-					buf->st_rdev = (major << 8 | minor);
-				}
-			}
-		}
-	}
+	if (fp->f_vnode != NULL &&
+	    fp->f_vnode->v_un.vu_cdev != NULL &&
+	    linux_driver_get_major_minor(fp->f_vnode->v_un.vu_cdev->si_name,
+					 &major, &minor) == 0)
+		buf->st_rdev = (major << 8 | minor);
 	fdrop(fp, td);
 }
 
@@ -128,6 +121,8 @@ translate_path_major_minor(struct thread
 	int fd;
 	int temp;
 
+	if (!S_ISCHR(buf->st_mode) && !S_ISBLK(buf->st_mode))
+		return;
 	temp = td->td_retval[0];
 	if (kern_open(td, path, UIO_SYSSPACE, O_RDONLY, 0) != 0)
 		return;
@@ -178,18 +173,19 @@ linux_newstat(struct thread *td, struct 
 #endif
 
 	error = kern_stat(td, path, UIO_SYSSPACE, &buf);
-	  if (!error && strlen(path) > strlen("/dev/pts/") &&
-	      !strncmp(path, "/dev/pts/", strlen("/dev/pts/"))
-	      && path[9] >= '0' && path[9] <= '9') {
-		  /*
-		   * Linux checks major and minors of the slave device to make
-		   * sure it's a pty device, so let's make him believe it is.
-		   */
-		  buf.st_rdev = (136 << 8);
-	  }
-
-	translate_path_major_minor(td, path, &buf);
-
+	if (!error) {
+		if (strlen(path) > strlen("/dev/pts/") &&
+		    !strncmp(path, "/dev/pts/", strlen("/dev/pts/")) &&
+		    path[9] >= '0' && path[9] <= '9') {
+			/*
+			 * Linux checks major and minors of the slave device
+			 * to make sure it's a pty device, so let's make him
+			 * believe it is.
+			 */
+			buf.st_rdev = (136 << 8);
+		} else
+			translate_path_major_minor(td, path, &buf);
+	}
 	LFREEPATH(path);
 	if (error)
 		return (error);



More information about the freebsd-emulation mailing list