Commit e075f591 authored by KAMEZAWA Hiroyuki's avatar KAMEZAWA Hiroyuki Committed by Linus Torvalds

seq_file: add seq_set_overflow(), seq_overflow()

It is undocumented but a seq_file's overflow state is indicated by
m->count == m->size.  Add seq_set_overflow() and seq_overflow() to
set/check overflow status explicitly.

Based on an idea from Eric Dumazet.

[akpm@linux-foundation.org: tweak code comment]
Signed-off-by: default avatarKAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 1b26c9b3
...@@ -13,6 +13,22 @@ ...@@ -13,6 +13,22 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/page.h> #include <asm/page.h>
/*
* seq_files have a buffer which can may overflow. When this happens a larger
* buffer is reallocated and all the data will be printed again.
* The overflow state is true when m->count == m->size.
*/
static bool seq_overflow(struct seq_file *m)
{
return m->count == m->size;
}
static void seq_set_overflow(struct seq_file *m)
{
m->count = m->size;
}
/** /**
* seq_open - initialize sequential file * seq_open - initialize sequential file
* @file: file we initialize * @file: file we initialize
...@@ -92,7 +108,7 @@ static int traverse(struct seq_file *m, loff_t offset) ...@@ -92,7 +108,7 @@ static int traverse(struct seq_file *m, loff_t offset)
error = 0; error = 0;
m->count = 0; m->count = 0;
} }
if (m->count == m->size) if (seq_overflow(m))
goto Eoverflow; goto Eoverflow;
if (pos + m->count > offset) { if (pos + m->count > offset) {
m->from = offset - pos; m->from = offset - pos;
...@@ -234,7 +250,7 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) ...@@ -234,7 +250,7 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
break; break;
} }
err = m->op->show(m, p); err = m->op->show(m, p);
if (m->count == m->size || err) { if (seq_overflow(m) || err) {
m->count = offs; m->count = offs;
if (likely(err <= 0)) if (likely(err <= 0))
break; break;
...@@ -361,7 +377,7 @@ int seq_escape(struct seq_file *m, const char *s, const char *esc) ...@@ -361,7 +377,7 @@ int seq_escape(struct seq_file *m, const char *s, const char *esc)
*p++ = '0' + (c & 07); *p++ = '0' + (c & 07);
continue; continue;
} }
m->count = m->size; seq_set_overflow(m);
return -1; return -1;
} }
m->count = p - m->buf; m->count = p - m->buf;
...@@ -383,7 +399,7 @@ int seq_printf(struct seq_file *m, const char *f, ...) ...@@ -383,7 +399,7 @@ int seq_printf(struct seq_file *m, const char *f, ...)
return 0; return 0;
} }
} }
m->count = m->size; seq_set_overflow(m);
return -1; return -1;
} }
EXPORT_SYMBOL(seq_printf); EXPORT_SYMBOL(seq_printf);
...@@ -512,7 +528,7 @@ int seq_bitmap(struct seq_file *m, const unsigned long *bits, ...@@ -512,7 +528,7 @@ int seq_bitmap(struct seq_file *m, const unsigned long *bits,
return 0; return 0;
} }
} }
m->count = m->size; seq_set_overflow(m);
return -1; return -1;
} }
EXPORT_SYMBOL(seq_bitmap); EXPORT_SYMBOL(seq_bitmap);
...@@ -528,7 +544,7 @@ int seq_bitmap_list(struct seq_file *m, const unsigned long *bits, ...@@ -528,7 +544,7 @@ int seq_bitmap_list(struct seq_file *m, const unsigned long *bits,
return 0; return 0;
} }
} }
m->count = m->size; seq_set_overflow(m);
return -1; return -1;
} }
EXPORT_SYMBOL(seq_bitmap_list); EXPORT_SYMBOL(seq_bitmap_list);
...@@ -639,7 +655,7 @@ int seq_puts(struct seq_file *m, const char *s) ...@@ -639,7 +655,7 @@ int seq_puts(struct seq_file *m, const char *s)
m->count += len; m->count += len;
return 0; return 0;
} }
m->count = m->size; seq_set_overflow(m);
return -1; return -1;
} }
EXPORT_SYMBOL(seq_puts); EXPORT_SYMBOL(seq_puts);
...@@ -673,7 +689,7 @@ int seq_put_decimal_ull(struct seq_file *m, char delimiter, ...@@ -673,7 +689,7 @@ int seq_put_decimal_ull(struct seq_file *m, char delimiter,
m->count += len; m->count += len;
return 0; return 0;
overflow: overflow:
m->count = m->size; seq_set_overflow(m);
return -1; return -1;
} }
EXPORT_SYMBOL(seq_put_decimal_ull); EXPORT_SYMBOL(seq_put_decimal_ull);
...@@ -683,7 +699,7 @@ int seq_put_decimal_ll(struct seq_file *m, char delimiter, ...@@ -683,7 +699,7 @@ int seq_put_decimal_ll(struct seq_file *m, char delimiter,
{ {
if (num < 0) { if (num < 0) {
if (m->count + 3 >= m->size) { if (m->count + 3 >= m->size) {
m->count = m->size; seq_set_overflow(m);
return -1; return -1;
} }
if (delimiter) if (delimiter)
...@@ -711,7 +727,7 @@ int seq_write(struct seq_file *seq, const void *data, size_t len) ...@@ -711,7 +727,7 @@ int seq_write(struct seq_file *seq, const void *data, size_t len)
seq->count += len; seq->count += len;
return 0; return 0;
} }
seq->count = seq->size; seq_set_overflow(seq);
return -1; return -1;
} }
EXPORT_SYMBOL(seq_write); EXPORT_SYMBOL(seq_write);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment