Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Miklos Szeredi and committed by
Al Viro
f8439806 f9098980

+77 -36
+39 -36
fs/seq_file.c
··· 429 429 */ 430 430 int seq_path(struct seq_file *m, struct path *path, char *esc) 431 431 { 432 - if (m->count < m->size) { 433 - char *s = m->buf + m->count; 434 - char *p = d_path(path, s, m->size - m->count); 432 + char *buf; 433 + size_t size = seq_get_buf(m, &buf); 434 + int res = -1; 435 + 436 + if (size) { 437 + char *p = d_path(path, buf, size); 435 438 if (!IS_ERR(p)) { 436 - s = mangle_path(s, p, esc); 437 - if (s) { 438 - p = m->buf + m->count; 439 - m->count = s - m->buf; 440 - return s - p; 441 - } 439 + char *end = mangle_path(buf, p, esc); 440 + if (end) 441 + res = end - buf; 442 442 } 443 443 } 444 - m->count = m->size; 445 - return -1; 444 + seq_commit(m, res); 445 + 446 + return res; 446 447 } 447 448 EXPORT_SYMBOL(seq_path); 448 449 ··· 455 454 int seq_path_root(struct seq_file *m, struct path *path, struct path *root, 456 455 char *esc) 457 456 { 458 - int err = -ENAMETOOLONG; 459 - if (m->count < m->size) { 460 - char *s = m->buf + m->count; 457 + char *buf; 458 + size_t size = seq_get_buf(m, &buf); 459 + int res = -ENAMETOOLONG; 460 + 461 + if (size) { 461 462 char *p; 462 463 463 464 spin_lock(&dcache_lock); 464 - p = __d_path(path, root, s, m->size - m->count); 465 + p = __d_path(path, root, buf, size); 465 466 spin_unlock(&dcache_lock); 466 - err = PTR_ERR(p); 467 + res = PTR_ERR(p); 467 468 if (!IS_ERR(p)) { 468 - s = mangle_path(s, p, esc); 469 - if (s) { 470 - p = m->buf + m->count; 471 - m->count = s - m->buf; 472 - return 0; 473 - } 474 - err = -ENAMETOOLONG; 469 + char *end = mangle_path(buf, p, esc); 470 + if (end) 471 + res = end - buf; 472 + else 473 + res = -ENAMETOOLONG; 475 474 } 476 475 } 477 - m->count = m->size; 478 - return err; 476 + seq_commit(m, res); 477 + 478 + return res < 0 ? res : 0; 479 479 } 480 480 481 481 /* ··· 484 482 */ 485 483 int seq_dentry(struct seq_file *m, struct dentry *dentry, char *esc) 486 484 { 487 - if (m->count < m->size) { 488 - char *s = m->buf + m->count; 489 - char *p = dentry_path(dentry, s, m->size - m->count); 485 + char *buf; 486 + size_t size = seq_get_buf(m, &buf); 487 + int res = -1; 488 + 489 + if (size) { 490 + char *p = dentry_path(dentry, buf, size); 490 491 if (!IS_ERR(p)) { 491 - s = mangle_path(s, p, esc); 492 - if (s) { 493 - p = m->buf + m->count; 494 - m->count = s - m->buf; 495 - return s - p; 496 - } 492 + char *end = mangle_path(buf, p, esc); 493 + if (end) 494 + res = end - buf; 497 495 } 498 496 } 499 - m->count = m->size; 500 - return -1; 497 + seq_commit(m, res); 498 + 499 + return res; 501 500 } 502 501 503 502 int seq_bitmap(struct seq_file *m, const unsigned long *bits,
+38
include/linux/seq_file.h
··· 35 35 36 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 76 char *mangle_path(char *s, char *p, char *esc); 39 77 int seq_open(struct file *, const struct seq_operations *); 40 78 ssize_t seq_read(struct file *, char __user *, size_t, loff_t *);