diff options
-rw-r--r-- | fs/sysfs/file.c | 39 | ||||
-rw-r--r-- | include/linux/kernfs.h | 9 |
2 files changed, 35 insertions, 13 deletions
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 9852450867cf..74e3478d9cb4 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c | |||
@@ -146,6 +146,7 @@ static ssize_t sysfs_kf_bin_read(struct sysfs_open_file *of, char *buf, | |||
146 | static void *kernfs_seq_start(struct seq_file *sf, loff_t *ppos) | 146 | static void *kernfs_seq_start(struct seq_file *sf, loff_t *ppos) |
147 | { | 147 | { |
148 | struct sysfs_open_file *of = sf->private; | 148 | struct sysfs_open_file *of = sf->private; |
149 | const struct kernfs_ops *ops; | ||
149 | 150 | ||
150 | /* | 151 | /* |
151 | * @of->mutex nests outside active ref and is just to ensure that | 152 | * @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) | |||
155 | if (!sysfs_get_active(of->sd)) | 156 | if (!sysfs_get_active(of->sd)) |
156 | return ERR_PTR(-ENODEV); | 157 | return ERR_PTR(-ENODEV); |
157 | 158 | ||
158 | /* | 159 | ops = kernfs_ops(of->sd); |
159 | * The same behavior and code as single_open(). Returns !NULL if | 160 | if (ops->seq_start) { |
160 | * pos is at the beginning; otherwise, NULL. | 161 | return ops->seq_start(sf, ppos); |
161 | */ | 162 | } else { |
162 | return NULL + !*ppos; | 163 | /* |
164 | * The same behavior and code as single_open(). Returns | ||
165 | * !NULL if pos is at the beginning; otherwise, NULL. | ||
166 | */ | ||
167 | return NULL + !*ppos; | ||
168 | } | ||
163 | } | 169 | } |
164 | 170 | ||
165 | static void *kernfs_seq_next(struct seq_file *sf, void *v, loff_t *ppos) | 171 | static void *kernfs_seq_next(struct seq_file *sf, void *v, loff_t *ppos) |
166 | { | 172 | { |
167 | /* | 173 | struct sysfs_open_file *of = sf->private; |
168 | * The same behavior and code as single_open(), always terminate | 174 | const struct kernfs_ops *ops = kernfs_ops(of->sd); |
169 | * after the initial read. | 175 | |
170 | */ | 176 | if (ops->seq_next) { |
171 | ++*ppos; | 177 | return ops->seq_next(sf, v, ppos); |
172 | return NULL; | 178 | } else { |
179 | /* | ||
180 | * The same behavior and code as single_open(), always | ||
181 | * terminate after the initial read. | ||
182 | */ | ||
183 | ++*ppos; | ||
184 | return NULL; | ||
185 | } | ||
173 | } | 186 | } |
174 | 187 | ||
175 | static void kernfs_seq_stop(struct seq_file *sf, void *v) | 188 | static void kernfs_seq_stop(struct seq_file *sf, void *v) |
176 | { | 189 | { |
177 | struct sysfs_open_file *of = sf->private; | 190 | struct sysfs_open_file *of = sf->private; |
191 | const struct kernfs_ops *ops = kernfs_ops(of->sd); | ||
192 | |||
193 | if (ops->seq_stop) | ||
194 | ops->seq_stop(sf, v); | ||
178 | 195 | ||
179 | sysfs_put_active(of->sd); | 196 | sysfs_put_active(of->sd); |
180 | mutex_unlock(&of->mutex); | 197 | mutex_unlock(&of->mutex); |
diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h index d0912cf02087..ba993ebcd81e 100644 --- a/include/linux/kernfs.h +++ b/include/linux/kernfs.h | |||
@@ -37,8 +37,9 @@ struct kernfs_ops { | |||
37 | /* | 37 | /* |
38 | * Read is handled by either seq_file or raw_read(). | 38 | * Read is handled by either seq_file or raw_read(). |
39 | * | 39 | * |
40 | * If seq_show() is present, seq_file path is active. The behavior | 40 | * If seq_show() is present, seq_file path is active. Other seq |
41 | * is equivalent to single_open(). @sf->private points to the | 41 | * operations are optional and if not implemented, the behavior is |
42 | * equivalent to single_open(). @sf->private points to the | ||
42 | * associated sysfs_open_file. | 43 | * associated sysfs_open_file. |
43 | * | 44 | * |
44 | * read() is bounced through kernel buffer and a read larger than | 45 | * read() is bounced through kernel buffer and a read larger than |
@@ -46,6 +47,10 @@ struct kernfs_ops { | |||
46 | */ | 47 | */ |
47 | int (*seq_show)(struct seq_file *sf, void *v); | 48 | int (*seq_show)(struct seq_file *sf, void *v); |
48 | 49 | ||
50 | void *(*seq_start)(struct seq_file *sf, loff_t *ppos); | ||
51 | void *(*seq_next)(struct seq_file *sf, void *v, loff_t *ppos); | ||
52 | void (*seq_stop)(struct seq_file *sf, void *v); | ||
53 | |||
49 | ssize_t (*read)(struct sysfs_open_file *of, char *buf, size_t bytes, | 54 | ssize_t (*read)(struct sysfs_open_file *of, char *buf, size_t bytes, |
50 | loff_t off); | 55 | loff_t off); |
51 | 56 | ||