devfs: Fix some issues

Fix issue with cdev private data usage with RTEMS iop structure. Add
support for cdev alias device names. Add support for cdev fstat.
This commit is contained in:
Kevin Kirspel 2017-05-12 08:16:27 -04:00 committed by Sebastian Huber
parent 6afe73d8f4
commit 817cbf7201
4 changed files with 145 additions and 24 deletions

View File

@ -204,7 +204,11 @@ devfs_destroy_cdevpriv(struct cdev_privdata *p)
free(p, M_CDEVPDATA);
}
#ifndef __rtems__
static void
#else /* __rtems__ */
void
#endif /* __rtems__ */
devfs_fpdrop(struct file *fp)
{
struct cdev_privdata *p;

View File

@ -854,9 +854,7 @@ make_dev_sv(struct make_dev_args *args1, struct cdev **dres,
#endif /* __rtems__ */
devfs_create(dev);
#ifndef __rtems__
clean_unrhdrl(devfs_inos);
#endif /* __rtems__ */
dev_unlock_and_free();
notify_create(dev, args.mda_flags);
@ -1020,9 +1018,7 @@ make_dev_alias_v(int flags, struct cdev **cdev, struct cdev *pdev,
dev->si_flags |= SI_NAMED;
devfs_create(dev);
dev_dependsl(pdev, dev);
#ifndef __rtems__
clean_unrhdrl(devfs_inos);
#endif /* __rtems__ */
dev_unlock();
notify_create(dev, flags);

View File

@ -199,14 +199,11 @@ struct file {
void *f_label; /* Place-holder for MAC label. */
#else /* __rtems__ */
rtems_libio_t f_io;
union {
struct cdev_privdata *fvn_cdevpriv;
/* (d) Private data for the cdev. */
} f_vnun;
#endif /* __rtems__ */
};
#ifdef __rtems__
#define f_data f_io.pathinfo.node_access_2
#define f_cdevpriv f_io.data1
static inline struct file *
rtems_bsd_iop_to_fp(rtems_libio_t *iop)
@ -283,8 +280,10 @@ rtems_bsd_error_to_status_and_errno(int error)
}
#endif /* __rtems__ */
#ifndef __rtems__
#define f_cdevpriv f_vnun.fvn_cdevpriv
#define f_advice f_vnun.fvn_advice
#endif /* __rtems__ */
#define FOFFSET_LOCKED 0x1
#define FOFFSET_LOCK_WAITING 0x2

View File

@ -37,6 +37,7 @@
#include <sys/file.h>
#include <sys/malloc.h>
#include <sys/proc.h>
#include <sys/poll.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@ -74,20 +75,40 @@ devfs_imfs_open(rtems_libio_t *iop, const char *path, int oflag, mode_t mode)
struct file *fp = rtems_bsd_iop_to_fp(iop);
struct thread *td = rtems_bsd_get_curthread_or_null();
struct file *fpop;
int error;
struct cdevsw *dsw;
int error, ref;
if (td != NULL) {
if (cdev == NULL) {
error = ENXIO;
goto err;
}
if (cdev->si_flags & SI_ALIAS) {
cdev = cdev->si_parent;
}
dsw = dev_refthread(cdev, &ref);
if (dsw == NULL) {
error = ENXIO;
goto err;
}
if (fp == NULL) {
dev_relthread(cdev, ref);
error = ENXIO;
goto err;
}
fpop = td->td_fpop;
curthread->td_fpop = fp;
error = cdev->si_devsw->d_open(cdev, oflag, 0, td);
error = dsw->d_open(cdev, oflag + 1, 0, td);
/* Clean up any cdevpriv upon error. */
if (error != 0)
devfs_clear_cdevpriv();
curthread->td_fpop = fpop;
dev_relthread(cdev, ref);
} else {
error = ENOMEM;
}
err:
return rtems_bsd_error_to_status_and_errno(error);
}
@ -99,17 +120,34 @@ devfs_imfs_close(rtems_libio_t *iop)
struct thread *td = rtems_bsd_get_curthread_or_null();
int flags = rtems_libio_to_fcntl_flags(iop->flags);
struct file *fpop;
int error;
struct cdevsw *dsw;
int error, ref;
if (td != NULL) {
if (cdev == NULL) {
error = ENXIO;
goto err;
}
if (cdev->si_flags & SI_ALIAS) {
cdev = cdev->si_parent;
}
dsw = dev_refthread(cdev, &ref);
if (dsw == NULL) {
error = ENXIO;
goto err;
}
fpop = td->td_fpop;
curthread->td_fpop = fp;
error = cdev->si_devsw->d_close(cdev, flags, 0, td);
error = dsw->d_close(cdev, flags, 0, td);
curthread->td_fpop = fpop;
dev_relthread(cdev, ref);
if (fp->f_cdevpriv != NULL)
devfs_fpdrop(fp);
} else {
error = ENOMEM;
}
err:
return rtems_bsd_error_to_status_and_errno(error);
}
@ -130,18 +168,33 @@ devfs_imfs_readv(rtems_libio_t *iop, const struct iovec *iov, int iovcnt,
.uio_td = td
};
struct file *fpop;
int error;
struct cdevsw *dsw;
int error, ref;
if (td != NULL) {
if (cdev == NULL) {
error = ENXIO;
goto err;
}
if (cdev->si_flags & SI_ALIAS) {
cdev = cdev->si_parent;
}
dsw = dev_refthread(cdev, &ref);
if (dsw == NULL) {
error = ENXIO;
goto err;
}
fpop = td->td_fpop;
curthread->td_fpop = fp;
error = cdev->si_devsw->d_read(cdev, &uio,
error = dsw->d_read(cdev, &uio,
rtems_libio_to_fcntl_flags(iop->flags));
td->td_fpop = fpop;
dev_relthread(cdev, ref);
} else {
error = ENOMEM;
}
err:
if (error == 0) {
return (total - uio.uio_resid);
} else {
@ -177,18 +230,33 @@ devfs_imfs_writev(rtems_libio_t *iop, const struct iovec *iov, int iovcnt,
.uio_td = td
};
struct file *fpop;
int error;
struct cdevsw *dsw;
int error, ref;
if (td != NULL) {
if (cdev == NULL) {
error = ENXIO;
goto err;
}
if (cdev->si_flags & SI_ALIAS) {
cdev = cdev->si_parent;
}
dsw = dev_refthread(cdev, &ref);
if (dsw == NULL) {
error = ENXIO;
goto err;
}
fpop = td->td_fpop;
curthread->td_fpop = fp;
error = cdev->si_devsw->d_write(cdev, &uio,
error = dsw->d_write(cdev, &uio,
rtems_libio_to_fcntl_flags(iop->flags));
td->td_fpop = fpop;
dev_relthread(cdev, ref);
} else {
error = ENOMEM;
}
err:
if (error == 0) {
return (total - uio.uio_resid);
} else {
@ -214,20 +282,50 @@ devfs_imfs_ioctl(rtems_libio_t *iop, ioctl_command_t request, void *buffer)
struct file *fp = rtems_bsd_iop_to_fp(iop);
struct thread *td = rtems_bsd_get_curthread_or_null();
struct file *fpop;
int error;
struct cdevsw *dsw;
int error, ref;
int flags = rtems_libio_to_fcntl_flags(iop->flags);
if (td != 0) {
if (cdev == NULL) {
error = ENXIO;
goto err;
}
if (cdev->si_flags & SI_ALIAS) {
cdev = cdev->si_parent;
}
dsw = dev_refthread(cdev, &ref);
if (dsw == NULL) {
error = ENXIO;
goto err;
}
fpop = td->td_fpop;
curthread->td_fpop = fp;
error = cdev->si_devsw->d_ioctl(cdev, request, buffer, flags,
error = dsw->d_ioctl(cdev, request, buffer, flags,
td);
td->td_fpop = fpop;
dev_relthread(cdev, ref);
} else {
error = ENOMEM;
}
return (rtems_bsd_error_to_status_and_errno(error));
err:
return rtems_bsd_error_to_status_and_errno(error);
}
static int
devfs_imfs_fstat(const rtems_filesystem_location_info_t *loc, struct stat *buf)
{
int rv = 0;
const IMFS_jnode_t *the_dev = loc->node_access;
if (the_dev != NULL) {
buf->st_mode = the_dev->st_mode;
} else {
rv = rtems_filesystem_default_fstat(loc, buf);
}
return rv;
}
static int
@ -237,12 +335,24 @@ devfs_imfs_poll(rtems_libio_t *iop, int events)
struct file *fp = rtems_bsd_iop_to_fp(iop);
struct thread *td = rtems_bsd_get_curthread_or_wait_forever();
struct file *fpop;
int error;
struct cdevsw *dsw;
int error, ref;
if (cdev == NULL) {
return POLLERR;
}
if (cdev->si_flags & SI_ALIAS) {
cdev = cdev->si_parent;
}
dsw = dev_refthread(cdev, &ref);
if (dsw == NULL) {
return POLLERR;
}
fpop = td->td_fpop;
curthread->td_fpop = fp;
error = cdev->si_devsw->d_poll(cdev, events, td);
error = dsw->d_poll(cdev, events, td);
td->td_fpop = fpop;
dev_relthread(cdev, ref);
return error;
}
@ -254,12 +364,24 @@ devfs_imfs_kqfilter(rtems_libio_t *iop, struct knote *kn)
struct file *fp = rtems_bsd_iop_to_fp(iop);
struct thread *td = rtems_bsd_get_curthread_or_wait_forever();
struct file *fpop;
int error;
struct cdevsw *dsw;
int error, ref;
if (cdev == NULL) {
return EINVAL;
}
if (cdev->si_flags & SI_ALIAS) {
cdev = cdev->si_parent;
}
dsw = dev_refthread(cdev, &ref);
if (dsw == NULL) {
return EINVAL;
}
fpop = td->td_fpop;
curthread->td_fpop = fp;
error = cdev->si_devsw->d_kqfilter(cdev, kn);
error = dsw->d_kqfilter(cdev, kn);
td->td_fpop = fpop;
dev_relthread(cdev, ref);
return error;
}
@ -271,7 +393,7 @@ static const rtems_filesystem_file_handlers_r devfs_imfs_handlers = {
.write_h = devfs_imfs_write,
.ioctl_h = devfs_imfs_ioctl,
.lseek_h = rtems_filesystem_default_lseek_file,
.fstat_h = rtems_filesystem_default_fstat,
.fstat_h = devfs_imfs_fstat,
.ftruncate_h = rtems_filesystem_default_ftruncate,
.fsync_h = rtems_filesystem_default_fsync_or_fdatasync,
.fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync,