Skip to content

Commit c199401

Browse files
committed
impl file operations for seq_file
1 parent 051aaa7 commit c199401

File tree

3 files changed

+96
-38
lines changed

3 files changed

+96
-38
lines changed

fs/seq_file.c

Lines changed: 35 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ static int traverse(struct seq_file *m, loff_t offset)
150150
*/
151151
ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
152152
{
153-
struct iovec iov = { .iov_base = buf, .iov_len = size};
153+
struct iovec iov = { .iov_base = buf, .iov_len = size };
154154
struct kiocb kiocb;
155155
struct iov_iter iter;
156156
ssize_t ret;
@@ -217,20 +217,20 @@ ssize_t seq_read_iter(struct kiocb *iocb, struct iov_iter *iter)
217217
m->count -= n;
218218
m->from += n;
219219
copied += n;
220-
if (m->count) // hadn't managed to copy everything
220+
if (m->count) // hadn't managed to copy everything
221221
goto Done;
222222
}
223223
// get a non-empty record in the buffer
224224
m->from = 0;
225225
p = m->op->start(m, &m->index);
226226
while (1) {
227227
err = PTR_ERR(p);
228-
if (!p || IS_ERR(p)) // EOF or an error
228+
if (!p || IS_ERR(p)) // EOF or an error
229229
break;
230230
err = m->op->show(m, p);
231-
if (err < 0) // hard error
231+
if (err < 0) // hard error
232232
break;
233-
if (unlikely(err)) // ->show() says "skip it"
233+
if (unlikely(err)) // ->show() says "skip it"
234234
m->count = 0;
235235
if (unlikely(!m->count)) { // empty record
236236
p = m->op->next(m, p, &m->index);
@@ -261,16 +261,17 @@ ssize_t seq_read_iter(struct kiocb *iocb, struct iov_iter *iter)
261261

262262
p = m->op->next(m, p, &m->index);
263263
if (pos == m->index) {
264-
pr_info_ratelimited("buggy .next function %ps did not update position index\n",
265-
m->op->next);
264+
pr_info_ratelimited(
265+
"buggy .next function %ps did not update position index\n",
266+
m->op->next);
266267
m->index++;
267268
}
268-
if (!p || IS_ERR(p)) // no next record for us
269+
if (!p || IS_ERR(p)) // no next record for us
269270
break;
270271
if (m->count >= iov_iter_count(iter))
271272
break;
272273
err = m->op->show(m, p);
273-
if (err > 0) { // ->show() says "skip it"
274+
if (err > 0) { // ->show() says "skip it"
274275
m->count = offs;
275276
} else if (err || seq_has_overflowed(m)) {
276277
m->count = offs;
@@ -591,7 +592,7 @@ int single_open(struct file *file, int (*show)(struct seq_file *, void *),
591592
EXPORT_SYMBOL(single_open);
592593

593594
int single_open_size(struct file *file, int (*show)(struct seq_file *, void *),
594-
void *data, size_t size)
595+
void *data, size_t size)
595596
{
596597
char *buf = seq_buf_alloc(size);
597598
int ret;
@@ -610,7 +611,8 @@ EXPORT_SYMBOL(single_open_size);
610611

611612
int single_release(struct inode *inode, struct file *file)
612613
{
613-
const struct seq_operations *op = ((struct seq_file *)file->private_data)->op;
614+
const struct seq_operations *op =
615+
((struct seq_file *)file->private_data)->op;
614616
int res = seq_release(inode, file);
615617
kfree(op);
616618
return res;
@@ -628,13 +630,14 @@ int seq_release_private(struct inode *inode, struct file *file)
628630
EXPORT_SYMBOL(seq_release_private);
629631

630632
void *__seq_open_private(struct file *f, const struct seq_operations *ops,
631-
int psize)
633+
int psize)
632634
{
633635
int rc;
634636
void *private;
635637
struct seq_file *seq;
636638

637-
private = kzalloc(psize, GFP_KERNEL_ACCOUNT);
639+
private
640+
= kzalloc(psize, GFP_KERNEL_ACCOUNT);
638641
if (private == NULL)
639642
goto out;
640643

@@ -654,7 +657,7 @@ void *__seq_open_private(struct file *f, const struct seq_operations *ops,
654657
EXPORT_SYMBOL(__seq_open_private);
655658

656659
int seq_open_private(struct file *filp, const struct seq_operations *ops,
657-
int psize)
660+
int psize)
658661
{
659662
return __seq_open_private(filp, ops, psize) ? 0 : -ENOMEM;
660663
}
@@ -696,7 +699,7 @@ EXPORT_SYMBOL(seq_puts);
696699
* In usual cases, it will be better to use seq_printf(). It's easier to read.
697700
*/
698701
void seq_put_decimal_ull_width(struct seq_file *m, const char *delimiter,
699-
unsigned long long num, unsigned int width)
702+
unsigned long long num, unsigned int width)
700703
{
701704
int len;
702705

@@ -747,7 +750,7 @@ EXPORT_SYMBOL(seq_put_decimal_ull);
747750
* In usual cases, it will be better to use seq_printf(). It's easier to read.
748751
*/
749752
void seq_put_hex_ll(struct seq_file *m, const char *delimiter,
750-
unsigned long long v, unsigned int width)
753+
unsigned long long v, unsigned int width)
751754
{
752755
unsigned int len;
753756
int i;
@@ -780,7 +783,8 @@ void seq_put_hex_ll(struct seq_file *m, const char *delimiter,
780783
m->count += len;
781784
}
782785

783-
void seq_put_decimal_ll(struct seq_file *m, const char *delimiter, long long num)
786+
void seq_put_decimal_ll(struct seq_file *m, const char *delimiter,
787+
long long num)
784788
{
785789
int len;
786790

@@ -904,7 +908,7 @@ struct list_head *seq_list_start(struct list_head *head, loff_t pos)
904908
{
905909
struct list_head *lh;
906910

907-
list_for_each(lh, head)
911+
list_for_each (lh, head)
908912
if (pos-- == 0)
909913
return lh;
910914

@@ -942,7 +946,7 @@ struct hlist_node *seq_hlist_start(struct hlist_head *head, loff_t pos)
942946
{
943947
struct hlist_node *node;
944948

945-
hlist_for_each(node, head)
949+
hlist_for_each (node, head)
946950
if (pos-- == 0)
947951
return node;
948952
return NULL;
@@ -998,12 +1002,11 @@ EXPORT_SYMBOL(seq_hlist_next);
9981002
* the _rcu list-mutation primitives such as hlist_add_head_rcu()
9991003
* as long as the traversal is guarded by rcu_read_lock().
10001004
*/
1001-
struct hlist_node *seq_hlist_start_rcu(struct hlist_head *head,
1002-
loff_t pos)
1005+
struct hlist_node *seq_hlist_start_rcu(struct hlist_head *head, loff_t pos)
10031006
{
10041007
struct hlist_node *node;
10051008

1006-
__hlist_for_each_rcu(node, head)
1009+
__hlist_for_each_rcu (node, head)
10071010
if (pos-- == 0)
10081011
return node;
10091012
return NULL;
@@ -1022,8 +1025,7 @@ EXPORT_SYMBOL(seq_hlist_start_rcu);
10221025
* the _rcu list-mutation primitives such as hlist_add_head_rcu()
10231026
* as long as the traversal is guarded by rcu_read_lock().
10241027
*/
1025-
struct hlist_node *seq_hlist_start_head_rcu(struct hlist_head *head,
1026-
loff_t pos)
1028+
struct hlist_node *seq_hlist_start_head_rcu(struct hlist_head *head, loff_t pos)
10271029
{
10281030
if (!pos)
10291031
return SEQ_START_TOKEN;
@@ -1044,8 +1046,7 @@ EXPORT_SYMBOL(seq_hlist_start_head_rcu);
10441046
* the _rcu list-mutation primitives such as hlist_add_head_rcu()
10451047
* as long as the traversal is guarded by rcu_read_lock().
10461048
*/
1047-
struct hlist_node *seq_hlist_next_rcu(void *v,
1048-
struct hlist_head *head,
1049+
struct hlist_node *seq_hlist_next_rcu(void *v, struct hlist_head *head,
10491050
loff_t *ppos)
10501051
{
10511052
struct hlist_node *node = v;
@@ -1066,13 +1067,13 @@ EXPORT_SYMBOL(seq_hlist_next_rcu);
10661067
*
10671068
* Called at seq_file->op->start().
10681069
*/
1069-
struct hlist_node *
1070-
seq_hlist_start_percpu(struct hlist_head __percpu *head, int *cpu, loff_t pos)
1070+
struct hlist_node *seq_hlist_start_percpu(struct hlist_head __percpu *head,
1071+
int *cpu, loff_t pos)
10711072
{
10721073
struct hlist_node *node;
10731074

1074-
for_each_possible_cpu(*cpu) {
1075-
hlist_for_each(node, per_cpu_ptr(head, *cpu)) {
1075+
for_each_possible_cpu (*cpu) {
1076+
hlist_for_each (node, per_cpu_ptr(head, *cpu)) {
10761077
if (pos-- == 0)
10771078
return node;
10781079
}
@@ -1090,9 +1091,9 @@ EXPORT_SYMBOL(seq_hlist_start_percpu);
10901091
*
10911092
* Called at seq_file->op->next().
10921093
*/
1093-
struct hlist_node *
1094-
seq_hlist_next_percpu(void *v, struct hlist_head __percpu *head,
1095-
int *cpu, loff_t *pos)
1094+
struct hlist_node *seq_hlist_next_percpu(void *v,
1095+
struct hlist_head __percpu *head,
1096+
int *cpu, loff_t *pos)
10961097
{
10971098
struct hlist_node *node = v;
10981099

@@ -1114,5 +1115,5 @@ EXPORT_SYMBOL(seq_hlist_next_percpu);
11141115

11151116
void __init seq_file_init(void)
11161117
{
1117-
seq_file_cache = KMEM_CACHE(seq_file, SLAB_ACCOUNT|SLAB_PANIC);
1118+
seq_file_cache = KMEM_CACHE(seq_file, SLAB_ACCOUNT | SLAB_PANIC);
11181119
}

rust/kernel/bindings_helper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include <linux/cdev.h>
44
#include <linux/clk.h>
5+
#include <linux/debugfs.h>
56
#include <linux/errname.h>
67
#include <linux/fs.h>
78
#include <linux/module.h>

rust/kernel/seq_file.rs

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,7 @@ extern "C" fn start_callback<T: SeqOperations>(
157157
// from `proc_create_seq_private` on the C side with data created via
158158
// `T::DataWrapper::into_pointer`. We don't move the data in the wrapper
159159
// so the pointer will remain valid for later calls.
160-
let data_wrapper =
161-
unsafe { T::DataWrapper::from_pointer(bindings::PDE_DATA((*(*m).file).f_inode)) };
160+
let data_wrapper = unsafe { T::DataWrapper::from_pointer((*m).private) };
162161
let iterator = data_wrapper.start().ok();
163162
// Data is still used in the `proc_dir_entry`.
164163
mem::forget(data_wrapper);
@@ -183,14 +182,71 @@ extern "C" fn start_callback<T: SeqOperations>(
183182
pub(crate) struct SeqFileOperationsVTable<T>(PhantomData<T>);
184183

185184
impl<T: SeqOperations> SeqFileOperationsVTable<T> {
186-
const VTABLE: bindings::seq_operations = bindings::seq_operations {
185+
const SEQ_VTABLE: bindings::seq_operations = bindings::seq_operations {
187186
start: Some(start_callback::<T>),
188187
stop: Some(stop_callback::<T>),
189188
next: Some(next_callback::<T>),
190189
show: Some(show_callback::<T>),
191190
};
192191

193-
pub(crate) const fn build() -> &'static bindings::seq_operations {
192+
// TODOABK: safety
193+
pub(crate) const unsafe fn seq_build() -> &'static bindings::seq_operations {
194+
&Self::SEQ_VTABLE
195+
}
196+
197+
extern "C" fn open_callback(
198+
inode: *mut bindings::inode,
199+
file: *mut bindings::file,
200+
) -> c_types::c_int {
201+
// TODOABK: docs
202+
unsafe {
203+
bindings::seq_open_private(
204+
file,
205+
&Self::SEQ_VTABLE as *const _ as *mut bindings::seq_operations,
206+
// TODOABK: how to convert safely?
207+
mem::size_of::<T::DataWrapper>() as i32,
208+
)
209+
}
210+
}
211+
212+
const VTABLE: bindings::file_operations = bindings::file_operations {
213+
open: Some(Self::open_callback),
214+
release: Some(bindings::seq_release_private),
215+
read: Some(bindings::seq_read),
216+
llseek: Some(bindings::seq_lseek),
217+
218+
check_flags: None,
219+
compat_ioctl: None,
220+
copy_file_range: None,
221+
fallocate: None,
222+
fadvise: None,
223+
fasync: None,
224+
flock: None,
225+
flush: None,
226+
fsync: None,
227+
get_unmapped_area: None,
228+
iterate: None,
229+
iterate_shared: None,
230+
iopoll: None,
231+
lock: None,
232+
mmap: None,
233+
mmap_supported_flags: 0,
234+
owner: ptr::null_mut(),
235+
poll: None,
236+
read_iter: None,
237+
remap_file_range: None,
238+
sendpage: None,
239+
setlease: None,
240+
show_fdinfo: None,
241+
splice_read: None,
242+
splice_write: None,
243+
unlocked_ioctl: None,
244+
write: None,
245+
write_iter: None,
246+
};
247+
248+
// TODOABK: safety
249+
pub(crate) const unsafe fn build() -> &'static bindings::file_operations {
194250
&Self::VTABLE
195251
}
196252
}

0 commit comments

Comments
 (0)