diff options
author | jkim <jkim@FreeBSD.org> | 2006-12-04 22:38:52 +0000 |
---|---|---|
committer | jkim <jkim@FreeBSD.org> | 2006-12-04 22:38:52 +0000 |
commit | 7d0068dacdbbbe473e388eba9e0c24a2ce548769 (patch) | |
tree | 73522ddb38d47b1404ef928876b9ea483a54136d /sys/compat/linux/linux_stats.c | |
parent | ff9c89ea112656bad19d3fdda0f118752731a4df (diff) | |
download | FreeBSD-src-7d0068dacdbbbe473e388eba9e0c24a2ce548769.zip FreeBSD-src-7d0068dacdbbbe473e388eba9e0c24a2ce548769.tar.gz |
MFP4: 109652
Fixes for 'blocking in fifoor state' problem of LTP tests.
linux_*stat*() functions were opening files with O_RDONLY to get
major/minor pair for char/block special files. Unfortunately,
when these functions are used against fifo, it is blocked forever
because there is no writer. Instead, we only open char/block special
files for major/minor conversion. We have to get rid of kern_open()
entirely from translate_path_major_minor() but today is not the day.
While I am here, add checks for errors before calling
translate_path_major_minor().
Diffstat (limited to 'sys/compat/linux/linux_stats.c')
-rw-r--r-- | sys/compat/linux/linux_stats.c | 77 |
1 files changed, 38 insertions, 39 deletions
diff --git a/sys/compat/linux/linux_stats.c b/sys/compat/linux/linux_stats.c index 09d0904..84feced 100644 --- a/sys/compat/linux/linux_stats.c +++ b/sys/compat/linux/linux_stats.c @@ -100,23 +100,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); } @@ -129,6 +122,8 @@ translate_path_major_minor(struct thread *td, char *path, struct stat *buf) 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; @@ -179,18 +174,19 @@ linux_newstat(struct thread *td, struct linux_newstat_args *args) #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); @@ -212,7 +208,8 @@ linux_newlstat(struct thread *td, struct linux_newlstat_args *args) #endif error = kern_lstat(td, path, UIO_SYSSPACE, &sb); - translate_path_major_minor(td, path, &sb); + if (!error) + translate_path_major_minor(td, path, &sb); LFREEPATH(path); if (error) return (error); @@ -524,18 +521,19 @@ linux_stat64(struct thread *td, struct linux_stat64_args *args) #endif error = kern_stat(td, filename, UIO_SYSSPACE, &buf); - if (!error && strlen(filename) > strlen("/dev/pts/") && - !strncmp(filename, "/dev/pts/", strlen("/dev/pts/")) - && filename[9] >= '0' && filename[9] <= '9') { - /* - * Linux checks major and minors of the slave device to make - * sure it's a pty deivce, so let's make him believe it is. - */ - buf.st_rdev = (136 << 8); + if (!error) { + if (strlen(filename) > strlen("/dev/pts/") && + !strncmp(filename, "/dev/pts/", strlen("/dev/pts/")) && + filename[9] >= '0' && filename[9] <= '9') { + /* + * Linux checks major and minors of the slave device + * to make sure it's a pty deivce, so let's make him + * believe it is. + */ + buf.st_rdev = (136 << 8); + } else + translate_path_major_minor(td, filename, &buf); } - - translate_path_major_minor(td, filename, &buf); - LFREEPATH(filename); if (error) return (error); @@ -557,7 +555,8 @@ linux_lstat64(struct thread *td, struct linux_lstat64_args *args) #endif error = kern_lstat(td, filename, UIO_SYSSPACE, &sb); - translate_path_major_minor(td, filename, &sb); + if (!error) + translate_path_major_minor(td, filename, &sb); LFREEPATH(filename); if (error) return (error); |