X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=fs%2Fseq_file.c;h=853770274f200ae36b49929b2afe55368ec1c047;hb=df8ea19b5d2e7512095bb1e0737513b8da196d64;hp=10690aa401c7740fbd3d7cab8548e618f89f8474;hpb=ea14fad0d416354a4e9bb1a04f32acba706f9548;p=linux-2.6 diff --git a/fs/seq_file.c b/fs/seq_file.c index 10690aa401..853770274f 100644 --- a/fs/seq_file.c +++ b/fs/seq_file.c @@ -177,21 +177,23 @@ EXPORT_SYMBOL(seq_read); static int traverse(struct seq_file *m, loff_t offset) { - loff_t pos = 0; + loff_t pos = 0, index; int error = 0; void *p; m->version = 0; - m->index = 0; + index = 0; m->count = m->from = 0; - if (!offset) + if (!offset) { + m->index = index; return 0; + } if (!m->buf) { m->buf = kmalloc(m->size = PAGE_SIZE, GFP_KERNEL); if (!m->buf) return -ENOMEM; } - p = m->op->start(m, &m->index); + p = m->op->start(m, &index); while (p) { error = PTR_ERR(p); if (IS_ERR(p)) @@ -204,15 +206,17 @@ static int traverse(struct seq_file *m, loff_t offset) if (pos + m->count > offset) { m->from = offset - pos; m->count -= m->from; + m->index = index; break; } pos += m->count; m->count = 0; if (pos == offset) { - m->index++; + index++; + m->index = index; break; } - p = m->op->next(m, p, &m->index); + p = m->op->next(m, p, &index); } m->op->stop(m, p); return error; @@ -260,8 +264,8 @@ loff_t seq_lseek(struct file *file, loff_t offset, int origin) } } } - mutex_unlock(&m->lock); file->f_version = m->version; + mutex_unlock(&m->lock); return retval; } EXPORT_SYMBOL(seq_lseek); @@ -269,7 +273,7 @@ EXPORT_SYMBOL(seq_lseek); /** * seq_release - free the structures associated with sequential file. * @file: file in question - * @inode: file->f_dentry->d_inode + * @inode: file->f_path.dentry->d_inode * * Frees the structures associated with sequential file; can be used * as ->f_op->release() if you don't have private data to destroy. @@ -338,13 +342,11 @@ int seq_printf(struct seq_file *m, const char *f, ...) } EXPORT_SYMBOL(seq_printf); -int seq_path(struct seq_file *m, - struct vfsmount *mnt, struct dentry *dentry, - char *esc) +int seq_path(struct seq_file *m, struct path *path, char *esc) { if (m->count < m->size) { char *s = m->buf + m->count; - char *p = d_path(dentry, mnt, s, m->size - m->count); + char *p = d_path(path, s, m->size - m->count); if (!IS_ERR(p)) { while (s <= p) { char c = *p++; @@ -425,6 +427,39 @@ int seq_release_private(struct inode *inode, struct file *file) } EXPORT_SYMBOL(seq_release_private); +void *__seq_open_private(struct file *f, const struct seq_operations *ops, + int psize) +{ + int rc; + void *private; + struct seq_file *seq; + + private = kzalloc(psize, GFP_KERNEL); + if (private == NULL) + goto out; + + rc = seq_open(f, ops); + if (rc < 0) + goto out_free; + + seq = f->private_data; + seq->private = private; + return private; + +out_free: + kfree(private); +out: + return NULL; +} +EXPORT_SYMBOL(__seq_open_private); + +int seq_open_private(struct file *filp, const struct seq_operations *ops, + int psize) +{ + return __seq_open_private(filp, ops, psize) ? 0 : -ENOMEM; +} +EXPORT_SYMBOL(seq_open_private); + int seq_putc(struct seq_file *m, char c) { if (m->count < m->size) { @@ -447,3 +482,37 @@ int seq_puts(struct seq_file *m, const char *s) return -1; } EXPORT_SYMBOL(seq_puts); + +struct list_head *seq_list_start(struct list_head *head, loff_t pos) +{ + struct list_head *lh; + + list_for_each(lh, head) + if (pos-- == 0) + return lh; + + return NULL; +} + +EXPORT_SYMBOL(seq_list_start); + +struct list_head *seq_list_start_head(struct list_head *head, loff_t pos) +{ + if (!pos) + return head; + + return seq_list_start(head, pos - 1); +} + +EXPORT_SYMBOL(seq_list_start_head); + +struct list_head *seq_list_next(void *v, struct list_head *head, loff_t *ppos) +{ + struct list_head *lh; + + lh = ((struct list_head *)v)->next; + ++*ppos; + return lh == head ? NULL : lh; +} + +EXPORT_SYMBOL(seq_list_next);