diff options
| author | Miklos Szeredi <mszeredi@suse.cz> | 2009-09-21 08:48:36 -0400 |
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2009-09-24 07:47:35 -0400 |
| commit | f84398068d9c2babe41500504ef247ae07081857 (patch) | |
| tree | 7306df97a7ee62f314f4db152fb2afceff156988 | |
| parent | f9098980ffea9c749622ff8ddf3b6d5831902a46 (diff) | |
vfs: seq_file: add helpers for data filling
Add two helpers that allow access to the seq_file's own buffer, but
hide the internal details of seq_files.
This allows easier implementation of special purpose filling
functions. It also cleans up some existing functions which duplicated
the seq_file logic.
Make these inline functions in seq_file.h, as suggested by Al.
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Acked-by: Hugh Dickins <hugh.dickins@tiscali.co.uk>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
| -rw-r--r-- | fs/seq_file.c | 75 | ||||
| -rw-r--r-- | include/linux/seq_file.h | 38 |
2 files changed, 77 insertions, 36 deletions
diff --git a/fs/seq_file.c b/fs/seq_file.c index 66efd0aa8fb3..eae7d9dbf3ff 100644 --- a/fs/seq_file.c +++ b/fs/seq_file.c | |||
| @@ -429,20 +429,21 @@ EXPORT_SYMBOL(mangle_path); | |||
| 429 | */ | 429 | */ |
| 430 | int seq_path(struct seq_file *m, struct path *path, char *esc) | 430 | int seq_path(struct seq_file *m, struct path *path, char *esc) |
| 431 | { | 431 | { |
| 432 | if (m->count < m->size) { | 432 | char *buf; |
| 433 | char *s = m->buf + m->count; | 433 | size_t size = seq_get_buf(m, &buf); |
| 434 | char *p = d_path(path, s, m->size - m->count); | 434 | int res = -1; |
| 435 | |||
| 436 | if (size) { | ||
| 437 | char *p = d_path(path, buf, size); | ||
| 435 | if (!IS_ERR(p)) { | 438 | if (!IS_ERR(p)) { |
| 436 | s = mangle_path(s, p, esc); | 439 | char *end = mangle_path(buf, p, esc); |
| 437 | if (s) { | 440 | if (end) |
| 438 | p = m->buf + m->count; | 441 | res = end - buf; |
| 439 | m->count = s - m->buf; | ||
| 440 | return s - p; | ||
| 441 | } | ||
| 442 | } | 442 | } |
| 443 | } | 443 | } |
| 444 | m->count = m->size; | 444 | seq_commit(m, res); |
| 445 | return -1; | 445 | |
| 446 | return res; | ||
| 446 | } | 447 | } |
| 447 | EXPORT_SYMBOL(seq_path); | 448 | EXPORT_SYMBOL(seq_path); |
| 448 | 449 | ||
| @@ -454,27 +455,28 @@ EXPORT_SYMBOL(seq_path); | |||
| 454 | int seq_path_root(struct seq_file *m, struct path *path, struct path *root, | 455 | int seq_path_root(struct seq_file *m, struct path *path, struct path *root, |
| 455 | char *esc) | 456 | char *esc) |
| 456 | { | 457 | { |
| 457 | int err = -ENAMETOOLONG; | 458 | char *buf; |
| 458 | if (m->count < m->size) { | 459 | size_t size = seq_get_buf(m, &buf); |
| 459 | char *s = m->buf + m->count; | 460 | int res = -ENAMETOOLONG; |
| 461 | |||
| 462 | if (size) { | ||
| 460 | char *p; | 463 | char *p; |
| 461 | 464 | ||
| 462 | spin_lock(&dcache_lock); | 465 | spin_lock(&dcache_lock); |
| 463 | p = __d_path(path, root, s, m->size - m->count); | 466 | p = __d_path(path, root, buf, size); |
| 464 | spin_unlock(&dcache_lock); | 467 | spin_unlock(&dcache_lock); |
| 465 | err = PTR_ERR(p); | 468 | res = PTR_ERR(p); |
| 466 | if (!IS_ERR(p)) { | 469 | if (!IS_ERR(p)) { |
| 467 | s = mangle_path(s, p, esc); | 470 | char *end = mangle_path(buf, p, esc); |
| 468 | if (s) { | 471 | if (end) |
| 469 | p = m->buf + m->count; | 472 | res = end - buf; |
| 470 | m->count = s - m->buf; | 473 | else |
| 471 | return 0; | 474 | res = -ENAMETOOLONG; |
| 472 | } | ||
| 473 | err = -ENAMETOOLONG; | ||
| 474 | } | 475 | } |
| 475 | } | 476 | } |
| 476 | m->count = m->size; | 477 | seq_commit(m, res); |
| 477 | return err; | 478 | |
| 479 | return res < 0 ? res : 0; | ||
| 478 | } | 480 | } |
| 479 | 481 | ||
| 480 | /* | 482 | /* |
| @@ -482,20 +484,21 @@ int seq_path_root(struct seq_file *m, struct path *path, struct path *root, | |||
| 482 | */ | 484 | */ |
| 483 | int seq_dentry(struct seq_file *m, struct dentry *dentry, char *esc) | 485 | int seq_dentry(struct seq_file *m, struct dentry *dentry, char *esc) |
| 484 | { | 486 | { |
| 485 | if (m->count < m->size) { | 487 | char *buf; |
| 486 | char *s = m->buf + m->count; | 488 | size_t size = seq_get_buf(m, &buf); |
| 487 | char *p = dentry_path(dentry, s, m->size - m->count); | 489 | int res = -1; |
| 490 | |||
| 491 | if (size) { | ||
| 492 | char *p = dentry_path(dentry, buf, size); | ||
| 488 | if (!IS_ERR(p)) { | 493 | if (!IS_ERR(p)) { |
| 489 | s = mangle_path(s, p, esc); | 494 | char *end = mangle_path(buf, p, esc); |
| 490 | if (s) { | 495 | if (end) |
| 491 | p = m->buf + m->count; | 496 | res = end - buf; |
| 492 | m->count = s - m->buf; | ||
| 493 | return s - p; | ||
| 494 | } | ||
| 495 | } | 497 | } |
| 496 | } | 498 | } |
| 497 | m->count = m->size; | 499 | seq_commit(m, res); |
| 498 | return -1; | 500 | |
| 501 | return res; | ||
| 499 | } | 502 | } |
| 500 | 503 | ||
| 501 | int seq_bitmap(struct seq_file *m, const unsigned long *bits, | 504 | int seq_bitmap(struct seq_file *m, const unsigned long *bits, |
diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h index 0c6a86b79596..8366d8f12e53 100644 --- a/include/linux/seq_file.h +++ b/include/linux/seq_file.h | |||
| @@ -35,6 +35,44 @@ struct seq_operations { | |||
| 35 | 35 | ||
| 36 | #define SEQ_SKIP 1 | 36 | #define SEQ_SKIP 1 |
| 37 | 37 | ||
| 38 | /** | ||
| 39 | * seq_get_buf - get buffer to write arbitrary data to | ||
| 40 | * @m: the seq_file handle | ||
| 41 | * @bufp: the beginning of the buffer is stored here | ||
| 42 | * | ||
| 43 | * Return the number of bytes available in the buffer, or zero if | ||
| 44 | * there's no space. | ||
| 45 | */ | ||
| 46 | static inline size_t seq_get_buf(struct seq_file *m, char **bufp) | ||
| 47 | { | ||
| 48 | BUG_ON(m->count > m->size); | ||
| 49 | if (m->count < m->size) | ||
| 50 | *bufp = m->buf + m->count; | ||
| 51 | else | ||
| 52 | *bufp = NULL; | ||
| 53 | |||
| 54 | return m->size - m->count; | ||
| 55 | } | ||
| 56 | |||
| 57 | /** | ||
| 58 | * seq_commit - commit data to the buffer | ||
| 59 | * @m: the seq_file handle | ||
| 60 | * @num: the number of bytes to commit | ||
| 61 | * | ||
| 62 | * Commit @num bytes of data written to a buffer previously acquired | ||
| 63 | * by seq_buf_get. To signal an error condition, or that the data | ||
| 64 | * didn't fit in the available space, pass a negative @num value. | ||
| 65 | */ | ||
| 66 | static inline void seq_commit(struct seq_file *m, int num) | ||
| 67 | { | ||
| 68 | if (num < 0) { | ||
| 69 | m->count = m->size; | ||
| 70 | } else { | ||
| 71 | BUG_ON(m->count + num > m->size); | ||
| 72 | m->count += num; | ||
| 73 | } | ||
| 74 | } | ||
| 75 | |||
| 38 | char *mangle_path(char *s, char *p, char *esc); | 76 | char *mangle_path(char *s, char *p, char *esc); |
| 39 | int seq_open(struct file *, const struct seq_operations *); | 77 | int seq_open(struct file *, const struct seq_operations *); |
| 40 | ssize_t seq_read(struct file *, char __user *, size_t, loff_t *); | 78 | ssize_t seq_read(struct file *, char __user *, size_t, loff_t *); |
