.stop = pppol2tp_seq_stop,
.show = pppol2tp_seq_show,
};
-#endif /* CONFIG_PROC_FS */
+
+static int pppol2tp_proc_open(struct inode *inode, struct file *file)
+{
+ struct net *net = pde_data(inode);
+ struct pppol2tp_seq_data *pd;
+
+ net = maybe_get_net(net);
+ 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);
+#endif
+ return 0;
+}
+
+static int pppol2tp_proc_release(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq = file->private_data;
+ struct pppol2tp_seq_data *pd = seq->private;
+
+ if (pd->session)
+ l2tp_session_put(pd->session);
+ if (pd->tunnel)
+ l2tp_tunnel_put(pd->tunnel);
+
+#ifdef CONFIG_NET_NS
+ put_net_track(pd->p.net, &pd->p.ns_tracker);
+#else
+ put_net(&init_net);
+#endif
+ return seq_release_private(inode, file);
+}
+
+static const struct proc_ops pppol2tp_proc_ops = {
+ .proc_open = pppol2tp_proc_open,
+ .proc_read = seq_read,
+ .proc_lseek = seq_lseek,
+ .proc_release = pppol2tp_proc_release,
+};
/*****************************************************************************
* Network namespace
struct proc_dir_entry *pde;
int err = 0;
- pde = proc_create_net("pppol2tp", 0444, net->proc_net,
- &pppol2tp_seq_ops, sizeof(struct pppol2tp_seq_data));
+ pde = proc_create_data("pppol2tp", 0444, net->proc_net,
+ &pppol2tp_proc_ops, net);
if (!pde) {
err = -ENOMEM;
goto out;
remove_proc_entry("pppol2tp", net->proc_net);
}
+#endif /* CONFIG_PROC_FS */
+
static struct pernet_operations pppol2tp_net_ops = {
+#ifdef CONFIG_PROC_FS
.init = pppol2tp_init_net,
.exit = pppol2tp_exit_net,
+#endif
};
/*****************************************************************************