Module: xenomai-head Branch: master Commit: 7b98f5db55f391b55f3b104961c31cfbc36426f2 URL: http://git.xenomai.org/?p=xenomai-head.git;a=commit;h=7b98f5db55f391b55f3b104961c31cfbc36426f2
Author: Philippe Gerum <[email protected]> Date: Mon Sep 27 10:58:21 2010 +0200 vfile: introduce O_EXCL handling --- include/nucleus/vfile.h | 31 ++++++++++++++++++++++++++++--- ksrc/nucleus/vfile.c | 35 ++++++++++++++++++++++++++++------- 2 files changed, 56 insertions(+), 10 deletions(-) diff --git a/include/nucleus/vfile.h b/include/nucleus/vfile.h index 3f42016..7aed7cc 100644 --- a/include/nucleus/vfile.h +++ b/include/nucleus/vfile.h @@ -40,8 +40,10 @@ struct xnvfile_lock_ops; struct xnvfile { struct proc_dir_entry *pde; + struct file *file; struct xnvfile_directory *parent; struct xnvfile_lock_ops *lockops; + int refcnt; void *private; }; @@ -109,13 +111,32 @@ struct xnvfile_input { */ struct xnvfile_regular_ops { /** + * @anchor regular_rewind This handler is called only once, + * when the virtual file is opened, before the @ref + * regular_show "begin() handler" is invoked. + * + * @param it A pointer to the vfile iterator which will be + * used to read the file contents. + * + * @return Zero should be returned upon success. Otherwise, a + * negative error code aborts the operation, and is passed + * back to the reader. + * + * @note This handler is optional. It should not be used to + * allocate resources but rather to perform consistency + * checks, since no closure call is issued in case the open + * sequence eventually fails. + */ + int (*rewind)(struct xnvfile_regular_iterator *it); + /** * @anchor regular_begin * This handler should prepare for iterating over the records - * upon a read request, according to the iterator data. + * upon a read request, starting from the specified position. * * @param it A pointer to the current vfile iterator. On * entry, it->pos is set to the (0-based) position of the - * first record to output. + * first record to output. This handler may be called multiple + * times with different position requests. * * @return A pointer to the first record to format and output, * to be passed to the @ref regular_show "show() handler" as @@ -148,7 +169,7 @@ struct xnvfile_regular_ops { * * @param it A pointer to the current vfile iterator. On * entry, it->pos is set to the (0-based) position of the - * first record to output. + * next record to output. * * @return A pointer to the next record to format and output, * to be passed to the @ref regular_show "show() handler" as @@ -573,6 +594,8 @@ static inline int xnvfile_link_p(struct xnvfile *entry) .pde = NULL, \ .parent = NULL, \ .private = NULL, \ + .file = NULL, \ + .refcnt = 0, \ } #define xnvfile_nodir { .entry = xnvfile_noentry } @@ -581,6 +604,8 @@ static inline int xnvfile_link_p(struct xnvfile *entry) #define xnvfile_parent(e) ((e)->entry.parent) #define xnvfile_priv(e) ((e)->entry.private) +#define xnvfile_nref(e) ((e)->entry.refcnt) +#define xnvfile_file(e) ((e)->entry.file) #define xnvfile_iterator_priv(it) ((void *)(&(it)->private)) extern struct xnvfile_nklock_class xnvfile_nucleus_lock; diff --git a/ksrc/nucleus/vfile.c b/ksrc/nucleus/vfile.c index b7a0774..896b17b 100644 --- a/ksrc/nucleus/vfile.c +++ b/ksrc/nucleus/vfile.c @@ -174,11 +174,15 @@ static int vfile_snapshot_open(struct inode *inode, struct file *file) return 0; } + if ((file->f_flags & O_EXCL) != 0 && xnvfile_nref(vfile) > 0) + return -EBUSY; + it = kzalloc(sizeof(*it) + vfile->privsz, GFP_KERNEL); if (it == NULL) return -ENOMEM; it->vfile = vfile; + xnvfile_file(vfile) = file; ret = vfile->entry.lockops->get(&vfile->entry); if (ret) @@ -290,6 +294,7 @@ finish: seq = file->private_data; it->seq = seq; seq->private = it; + xnvfile_nref(vfile)++; return 0; } @@ -302,6 +307,8 @@ static int vfile_snapshot_release(struct inode *inode, struct file *file) if (seq) { it = seq->private; if (it) { + --xnvfile_nref(it->vfile); + XENO_BUGON(NUCLEUS, it->vfile->entry.refcnt < 0); if (it->databuf) it->endfn(it, it->databuf); kfree(it); @@ -500,8 +507,10 @@ static int vfile_regular_open(struct inode *inode, struct file *file) struct seq_file *seq; int ret; - if ((file->f_mode & FMODE_WRITE) != 0 && - ops->store == NULL) + if ((file->f_flags & O_EXCL) != 0 && xnvfile_nref(vfile) > 0) + return -EBUSY; + + if ((file->f_mode & FMODE_WRITE) != 0 && ops->store == NULL) return -EACCES; if ((file->f_mode & FMODE_READ) == 0) { @@ -515,16 +524,25 @@ static int vfile_regular_open(struct inode *inode, struct file *file) it->vfile = vfile; it->pos = -1; + xnvfile_file(vfile) = file; - ret = seq_open(file, &vfile_regular_ops); - if (ret) { - kfree(it); - return ret; + if (ops->rewind) { + ret = ops->rewind(it); + if (ret) { + fail: + kfree(it); + return ret; + } } + ret = seq_open(file, &vfile_regular_ops); + if (ret) + goto fail; + seq = file->private_data; it->seq = seq; seq->private = it; + xnvfile_nref(vfile)++; return 0; } @@ -536,8 +554,11 @@ static int vfile_regular_release(struct inode *inode, struct file *file) if (seq) { it = seq->private; - if (it) + if (it) { + --xnvfile_nref(it->vfile); + XENO_BUGON(NUCLEUS, xnvfile_nref(it->vfile) < 0); kfree(it); + } return seq_release(inode, file); } _______________________________________________ Xenomai-git mailing list [email protected] https://mail.gna.org/listinfo/xenomai-git
