Declare the seq_operations and the size of the iterator state and let
procfs open and free the seq_file. ->proc_open() only takes the
reference to the network namespace now and ->proc_release() drops that
and the references the iterator holds. Reading the file then no longer
holds up its removal.
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
net/l2tp/l2tp_ppp.c | 20 ++++++++------------
1 file changed, 8 insertions(+), 12 deletions(-)
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c
index 4f311d473a64..499e37eb788a 100644
--- a/net/l2tp/l2tp_ppp.c
+++ b/net/l2tp/l2tp_ppp.c
@@ -1596,21 +1596,17 @@ static const struct seq_operations pppol2tp_seq_ops = {
.show = pppol2tp_seq_show,
};
+/* procfs opened the seq_file and allocated @pd */
static int pppol2tp_proc_open(struct inode *inode, struct file *file)
{
- struct net *net = pde_data(inode);
- struct pppol2tp_seq_data *pd;
+ struct seq_file *seq = file->private_data;
+ struct pppol2tp_seq_data *pd __maybe_unused = seq->private;
+ struct net *net;
- net = maybe_get_net(net);
+ net = maybe_get_net(pde_data(inode));
if (!net)
return -ENXIO;
- pd = __seq_open_private(file, &pppol2tp_seq_ops, sizeof(*pd));
- if (!pd) {
- put_net(net);
- return -ENOMEM;
- }
-
#ifdef CONFIG_NET_NS
pd->p.net = net;
netns_tracker_alloc(net, &pd->p.ns_tracker, GFP_KERNEL);@@ -1633,13 +1629,13 @@ static int pppol2tp_proc_release(struct inode *inode, struct file *file)
#else
put_net(&init_net);
#endif
- return seq_release_private(inode, file);
+ return 0;
}
static const struct proc_ops pppol2tp_proc_ops = {
+ .proc_seq_ops = &pppol2tp_seq_ops,
+ .proc_state_size = sizeof(struct pppol2tp_seq_data),
.proc_open = pppol2tp_proc_open,
- .proc_read = seq_read,
- .proc_lseek = seq_lseek,
.proc_release = pppol2tp_proc_release,
};
--
2.53.0