sysfs, kernfs: add kernfs_ops->seq_{start|next|stop}()
kernfs_ops currently only supports single_open() behavior which is pretty restrictive. Add optional callbacks ->seq_{start|next|stop}() which, when implemented, are invoked for seq_file traversal. This allows full seq_file functionality for kernfs users. This currently doesn't have any user and doesn't change any behavior. v2: Refreshed on top of the updated "sysfs, kernfs: prepare read path for kernfs". Signed-off-by: Tejun Heo <tj@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:

committed by
Greg Kroah-Hartman

parent
2d0cfbec2a
commit
d19b9846df
@@ -146,6 +146,7 @@ static ssize_t sysfs_kf_bin_read(struct sysfs_open_file *of, char *buf,
|
||||
static void *kernfs_seq_start(struct seq_file *sf, loff_t *ppos)
|
||||
{
|
||||
struct sysfs_open_file *of = sf->private;
|
||||
const struct kernfs_ops *ops;
|
||||
|
||||
/*
|
||||
* @of->mutex nests outside active ref and is just to ensure that
|
||||
@@ -155,26 +156,42 @@ static void *kernfs_seq_start(struct seq_file *sf, loff_t *ppos)
|
||||
if (!sysfs_get_active(of->sd))
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
/*
|
||||
* The same behavior and code as single_open(). Returns !NULL if
|
||||
* pos is at the beginning; otherwise, NULL.
|
||||
*/
|
||||
return NULL + !*ppos;
|
||||
ops = kernfs_ops(of->sd);
|
||||
if (ops->seq_start) {
|
||||
return ops->seq_start(sf, ppos);
|
||||
} else {
|
||||
/*
|
||||
* The same behavior and code as single_open(). Returns
|
||||
* !NULL if pos is at the beginning; otherwise, NULL.
|
||||
*/
|
||||
return NULL + !*ppos;
|
||||
}
|
||||
}
|
||||
|
||||
static void *kernfs_seq_next(struct seq_file *sf, void *v, loff_t *ppos)
|
||||
{
|
||||
/*
|
||||
* The same behavior and code as single_open(), always terminate
|
||||
* after the initial read.
|
||||
*/
|
||||
++*ppos;
|
||||
return NULL;
|
||||
struct sysfs_open_file *of = sf->private;
|
||||
const struct kernfs_ops *ops = kernfs_ops(of->sd);
|
||||
|
||||
if (ops->seq_next) {
|
||||
return ops->seq_next(sf, v, ppos);
|
||||
} else {
|
||||
/*
|
||||
* The same behavior and code as single_open(), always
|
||||
* terminate after the initial read.
|
||||
*/
|
||||
++*ppos;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void kernfs_seq_stop(struct seq_file *sf, void *v)
|
||||
{
|
||||
struct sysfs_open_file *of = sf->private;
|
||||
const struct kernfs_ops *ops = kernfs_ops(of->sd);
|
||||
|
||||
if (ops->seq_stop)
|
||||
ops->seq_stop(sf, v);
|
||||
|
||||
sysfs_put_active(of->sd);
|
||||
mutex_unlock(&of->mutex);
|
||||
|
Reference in New Issue
Block a user