aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2009-09-21 08:48:36 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2009-09-24 07:47:35 -0400
commitf84398068d9c2babe41500504ef247ae07081857 (patch)
tree7306df97a7ee62f314f4db152fb2afceff156988
parentf9098980ffea9c749622ff8ddf3b6d5831902a46 (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.c75
-rw-r--r--include/linux/seq_file.h38
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 */
430int seq_path(struct seq_file *m, struct path *path, char *esc) 430int 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}
447EXPORT_SYMBOL(seq_path); 448EXPORT_SYMBOL(seq_path);
448 449
@@ -454,27 +455,28 @@ EXPORT_SYMBOL(seq_path);
454int seq_path_root(struct seq_file *m, struct path *path, struct path *root, 455int 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 */
483int seq_dentry(struct seq_file *m, struct dentry *dentry, char *esc) 485int 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
501int seq_bitmap(struct seq_file *m, const unsigned long *bits, 504int 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 */
46static 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 */
66static 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
38char *mangle_path(char *s, char *p, char *esc); 76char *mangle_path(char *s, char *p, char *esc);
39int seq_open(struct file *, const struct seq_operations *); 77int seq_open(struct file *, const struct seq_operations *);
40ssize_t seq_read(struct file *, char __user *, size_t, loff_t *); 78ssize_t seq_read(struct file *, char __user *, size_t, loff_t *);