From owner-svn-src-head@FreeBSD.ORG Fri Feb 20 13:05:29 2009 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id A8A79106564A; Fri, 20 Feb 2009 13:05:29 +0000 (UTC) (envelope-from ed@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 928F78FC24; Fri, 20 Feb 2009 13:05:29 +0000 (UTC) (envelope-from ed@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n1KD5TMm029684; Fri, 20 Feb 2009 13:05:29 GMT (envelope-from ed@svn.freebsd.org) Received: (from ed@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n1KD5TGx029681; Fri, 20 Feb 2009 13:05:29 GMT (envelope-from ed@svn.freebsd.org) Message-Id: <200902201305.n1KD5TGx029681@svn.freebsd.org> From: Ed Schouten Date: Fri, 20 Feb 2009 13:05:29 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r188849 - in head/sys: compat/linux kern sys X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 20 Feb 2009 13:05:30 -0000 Author: ed Date: Fri Feb 20 13:05:29 2009 New Revision: 188849 URL: http://svn.freebsd.org/changeset/base/188849 Log: Don't make Linux stat() open character devices to resolve its name. The existing code calls kern_open() to resolve the vnode of a pathname right after a stat(). This is not correct, because it causes random character devices to be opened in /dev. This means ls'ing a tape streamer will cause it to rewind, for example. Changes I have made: - Add kern_statat_vnhook() to allow binary emulators to `post-process' struct stat, using the proper vnode. - Remove unneeded printf's from stat() and statfs(). - Make the Linuxolator use kern_statat_vnhook(), replacing translate_path_major_minor_at(). - Let translate_fd_major_minor() use vp->v_rdev instead of vp->v_un.vu_cdev. Result: crw-rw-rw- 1 root root 0, 14 Feb 20 13:54 /dev/ptmx crw--w---- 1 root adm 136, 0 Feb 20 14:03 /dev/pts/0 crw--w---- 1 root adm 136, 1 Feb 20 14:02 /dev/pts/1 crw--w---- 1 ed tty 136, 2 Feb 20 14:03 /dev/pts/2 Before this commit, ptmx also had a major number of 136, because it silently allocated and deallocated a pseudo-terminal. Device nodes that cannot be opened now have proper major/minor-numbers. Reviewed by: kib, netchild, rdivacky (thanks!) Modified: head/sys/compat/linux/linux_stats.c head/sys/kern/vfs_syscalls.c head/sys/sys/syscallsubr.h Modified: head/sys/compat/linux/linux_stats.c ============================================================================== --- head/sys/compat/linux/linux_stats.c Fri Feb 20 11:09:55 2009 (r188848) +++ head/sys/compat/linux/linux_stats.c Fri Feb 20 13:05:29 2009 (r188849) @@ -62,6 +62,44 @@ __FBSDID("$FreeBSD$"); #include +static void +translate_vnhook_major_minor(struct vnode *vp, struct stat *sb) +{ + int major, minor; + + if (vp->v_type == VCHR && vp->v_rdev != NULL && + linux_driver_get_major_minor(vp->v_rdev->si_name, + &major, &minor) == 0) { + sb->st_rdev = (major << 8 | minor); + } +} + +static int +linux_kern_statat(struct thread *td, int flag, int fd, char *path, + enum uio_seg pathseg, struct stat *sbp) +{ + + return (kern_statat_vnhook(td, flag, fd, path, pathseg, sbp, + translate_vnhook_major_minor)); +} + +static int +linux_kern_stat(struct thread *td, char *path, enum uio_seg pathseg, + struct stat *sbp) +{ + + return (linux_kern_statat(td, 0, AT_FDCWD, path, pathseg, sbp)); +} + +static int +linux_kern_lstat(struct thread *td, char *path, enum uio_seg pathseg, + struct stat *sbp) +{ + + return (linux_kern_statat(td, AT_SYMLINK_NOFOLLOW, AT_FDCWD, path, + pathseg, sbp)); +} + /* * XXX: This was removed from newstat_copyout(), and almost identical * XXX: code was in stat64_copyout(). findcdev() needs to be replaced @@ -102,14 +140,15 @@ static void translate_fd_major_minor(struct thread *td, int fd, struct stat *buf) { struct file *fp; + struct vnode *vp; int major, minor; if ((!S_ISCHR(buf->st_mode) && !S_ISBLK(buf->st_mode)) || fget(td, fd, &fp) != 0) return; - 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, + vp = fp->f_vnode; + if (vp != NULL && vp->v_rdev != NULL && + linux_driver_get_major_minor(vp->v_rdev->si_name, &major, &minor) == 0) { buf->st_rdev = (major << 8 | minor); } else if (fp->f_type == DTYPE_PTS) { @@ -124,32 +163,6 @@ translate_fd_major_minor(struct thread * fdrop(fp, td); } -static void -translate_path_major_minor_at(struct thread *td, char *path, - struct stat *buf, int dfd) -{ - struct proc *p = td->td_proc; - struct filedesc *fdp = p->p_fd; - int fd; - int temp; - - if (!S_ISCHR(buf->st_mode) && !S_ISBLK(buf->st_mode)) - return; - temp = td->td_retval[0]; - if (kern_openat(td, dfd, path, UIO_SYSSPACE, O_RDONLY, 0) != 0) - return; - fd = td->td_retval[0]; - td->td_retval[0] = temp; - translate_fd_major_minor(td, fd, buf); - fdclose(fdp, fdp->fd_ofiles[fd], fd, td); -} - -static inline void -translate_path_major_minor(struct thread *td, char *path, struct stat *buf) -{ - translate_path_major_minor_at(td, path, buf, AT_FDCWD); -} - static int newstat_copyout(struct stat *buf, void *ubuf) { @@ -187,9 +200,7 @@ linux_newstat(struct thread *td, struct printf(ARGS(newstat, "%s, *"), path); #endif - error = kern_stat(td, path, UIO_SYSSPACE, &buf); - if (!error) - translate_path_major_minor(td, path, &buf); + error = linux_kern_stat(td, path, UIO_SYSSPACE, &buf); LFREEPATH(path); if (error) return (error); @@ -210,9 +221,7 @@ linux_newlstat(struct thread *td, struct printf(ARGS(newlstat, "%s, *"), path); #endif - error = kern_lstat(td, path, UIO_SYSSPACE, &sb); - if (!error) - translate_path_major_minor(td, path, &sb); + error = linux_kern_lstat(td, path, UIO_SYSSPACE, &sb); LFREEPATH(path); if (error) return (error); @@ -279,12 +288,11 @@ linux_stat(struct thread *td, struct lin if (ldebug(stat)) printf(ARGS(stat, "%s, *"), path); #endif - error = kern_stat(td, path, UIO_SYSSPACE, &buf); + error = linux_kern_stat(td, path, UIO_SYSSPACE, &buf); if (error) { LFREEPATH(path); return (error); } - translate_path_major_minor(td, path, &buf); LFREEPATH(path); return(stat_copyout(&buf, args->up)); } @@ -302,12 +310,11 @@ linux_lstat(struct thread *td, struct li if (ldebug(lstat)) printf(ARGS(lstat, "%s, *"), path); #endif - error = kern_lstat(td, path, UIO_SYSSPACE, &buf); + error = linux_kern_lstat(td, path, UIO_SYSSPACE, &buf); if (error) { LFREEPATH(path); return (error); } - translate_path_major_minor(td, path, &buf); LFREEPATH(path); return(stat_copyout(&buf, args->up)); } @@ -526,9 +533,7 @@ linux_stat64(struct thread *td, struct l printf(ARGS(stat64, "%s, *"), filename); #endif - error = kern_stat(td, filename, UIO_SYSSPACE, &buf); - if (!error) - translate_path_major_minor(td, filename, &buf); + error = linux_kern_stat(td, filename, UIO_SYSSPACE, &buf); LFREEPATH(filename); if (error) return (error); @@ -549,9 +554,7 @@ linux_lstat64(struct thread *td, struct printf(ARGS(lstat64, "%s, *"), args->filename); #endif - error = kern_lstat(td, filename, UIO_SYSSPACE, &sb); - if (!error) - translate_path_major_minor(td, filename, &sb); + error = linux_kern_lstat(td, filename, UIO_SYSSPACE, &sb); LFREEPATH(filename); if (error) return (error); @@ -597,8 +600,7 @@ linux_fstatat64(struct thread *td, struc printf(ARGS(fstatat64, "%i, %s, %i"), args->dfd, path, args->flag); #endif - error = kern_statat(td, flag, dfd, path, UIO_SYSSPACE, &buf); - translate_path_major_minor_at(td, args->pathname, &buf, dfd); + error = linux_kern_statat(td, flag, dfd, path, UIO_SYSSPACE, &buf); if (!error) error = stat64_copyout(&buf, args->statbuf); LFREEPATH(path); Modified: head/sys/kern/vfs_syscalls.c ============================================================================== --- head/sys/kern/vfs_syscalls.c Fri Feb 20 11:09:55 2009 (r188848) +++ head/sys/kern/vfs_syscalls.c Fri Feb 20 13:05:29 2009 (r188849) @@ -339,8 +339,6 @@ kern_statfs(struct thread *td, char *pat out: vfs_unbusy(mp); VFS_UNLOCK_GIANT(vfslocked); - if (mtx_owned(&Giant)) - printf("statfs(%d): %s: %d\n", vfslocked, path, error); return (error); } @@ -2343,6 +2341,15 @@ int kern_statat(struct thread *td, int flag, int fd, char *path, enum uio_seg pathseg, struct stat *sbp) { + + return (kern_statat_vnhook(td, flag, fd, path, pathseg, sbp, NULL)); +} + +int +kern_statat_vnhook(struct thread *td, int flag, int fd, char *path, + enum uio_seg pathseg, struct stat *sbp, + void (*hook)(struct vnode *vp, struct stat *sbp)) +{ struct nameidata nd; struct stat sb; int error, vfslocked; @@ -2362,12 +2369,12 @@ kern_statat(struct thread *td, int flag, SDT_PROBE(vfs, , stat, mode, path, sb.st_mode, 0, 0, 0); if (S_ISREG(sb.st_mode)) SDT_PROBE(vfs, , stat, reg, path, pathseg, 0, 0, 0); + if (__predict_false(hook != NULL)) + hook(nd.ni_vp, &sb); } NDFREE(&nd, NDF_ONLY_PNBUF); vput(nd.ni_vp); VFS_UNLOCK_GIANT(vfslocked); - if (mtx_owned(&Giant)) - printf("stat(%d): %s\n", vfslocked, path); if (error) return (error); *sbp = sb; Modified: head/sys/sys/syscallsubr.h ============================================================================== --- head/sys/sys/syscallsubr.h Fri Feb 20 11:09:55 2009 (r188848) +++ head/sys/sys/syscallsubr.h Fri Feb 20 13:05:29 2009 (r188849) @@ -193,6 +193,9 @@ int kern_stat(struct thread *td, char *p struct stat *sbp); int kern_statat(struct thread *td, int flag, int fd, char *path, enum uio_seg pathseg, struct stat *sbp); +int kern_statat_vnhook(struct thread *td, int flag, int fd, char *path, + enum uio_seg pathseg, struct stat *sbp, + void (*hook)(struct vnode *vp, struct stat *sbp)); int kern_statfs(struct thread *td, char *path, enum uio_seg pathseg, struct statfs *buf); int kern_symlink(struct thread *td, char *path, char *link,