diff --git a/net/key/af_key.c b/net/key/af_key.c index 162fcea3324c..b3ac85e808ac 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -3734,21 +3734,15 @@ static struct net_proto_family pfkey_family_ops = { }; #ifdef CONFIG_PROC_FS -static int pfkey_read_proc(char *buffer, char **start, off_t offset, - int length, int *eof, void *data) +static int pfkey_seq_show(struct seq_file *f, void *v) { - off_t pos = 0; - off_t begin = 0; - int len = 0; struct sock *s; - struct hlist_node *node; - len += sprintf(buffer,"sk RefCnt Rmem Wmem User Inode\n"); - - read_lock(&pfkey_table_lock); - - sk_for_each(s, node, &pfkey_table) { - len += sprintf(buffer+len,"%p %-6d %-6u %-6u %-6u %-6lu", + s = (struct sock *)v; + if (v == SEQ_START_TOKEN) + seq_printf(f ,"sk RefCnt Rmem Wmem User Inode\n"); + else + seq_printf(f ,"%p %-6d %-6u %-6u %-6u %-6lu\n", s, atomic_read(&s->sk_refcnt), atomic_read(&s->sk_rmem_alloc), @@ -3756,40 +3750,68 @@ static int pfkey_read_proc(char *buffer, char **start, off_t offset, sock_i_uid(s), sock_i_ino(s) ); - - buffer[len++] = '\n'; - - pos = begin + len; - if (pos < offset) { - len = 0; - begin = pos; - } - if(pos > offset + length) - goto done; - } - *eof = 1; - -done: - read_unlock(&pfkey_table_lock); - - *start = buffer + (offset - begin); - len -= (offset - begin); - - if (len > length) - len = length; - if (len < 0) - len = 0; - - return len; + return 0; } +static void *pfkey_seq_start(struct seq_file *f, loff_t *ppos) +{ + struct sock *s; + struct hlist_node *node; + loff_t pos = *ppos; + + read_lock(&pfkey_table_lock); + if (pos == 0) + return SEQ_START_TOKEN; + + sk_for_each(s, node, &pfkey_table) + if (pos-- == 1) + return s; + + return NULL; +} + +static void *pfkey_seq_next(struct seq_file *f, void *v, loff_t *ppos) +{ + ++*ppos; + return (v == SEQ_START_TOKEN) ? + sk_head(&pfkey_table) : + sk_next((struct sock *)v); +} + +static void pfkey_seq_stop(struct seq_file *f, void *v) +{ + read_unlock(&pfkey_table_lock); +} + +static struct seq_operations pfkey_seq_ops = { + .start = pfkey_seq_start, + .next = pfkey_seq_next, + .stop = pfkey_seq_stop, + .show = pfkey_seq_show, +}; + +static int pfkey_seq_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &pfkey_seq_ops); +} + +static struct file_operations pfkey_proc_ops = { + .open = pfkey_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + static int pfkey_init_proc(void) { - if (create_proc_read_entry("pfkey", 0, init_net.proc_net, - pfkey_read_proc, NULL) == NULL) + struct proc_dir_entry *e; + + e = create_proc_entry("pfkey", 0, init_net.proc_net); + if (e == NULL) return -ENOMEM; - else - return 0; + + e->proc_fops = &pfkey_proc_ops; + return 0; } static void pfkey_exit_proc(void)