/* * Reads on sysfs are handled through seq_file, which takes care of hairy * details like buffering and seeking. The following function pipes * sysfs_ops->show() result through seq_file. */ static int sysfs_seq_show(struct seq_file *sf, void *v) { struct sysfs_open_file *of = sf->private; struct kobject *kobj = of->sd->s_parent->s_dir.kobj; const struct sysfs_ops *ops; char *buf; ssize_t count; /* acquire buffer and ensure that it's >= PAGE_SIZE */ count = seq_get_buf(sf, &buf); if (count < PAGE_SIZE) { seq_commit(sf, -1); return 0; } /* * Need @of->sd for attr and ops, its parent for kobj. @of->mutex * nests outside active ref and is just to ensure that the ops * aren't called concurrently for the same open file. */ mutex_lock(&of->mutex); if (!sysfs_get_active(of->sd)) { mutex_unlock(&of->mutex); return -ENODEV; } of->event = atomic_read(&of->sd->s_attr.open->event); /* * Lookup @ops and invoke show(). Control may reach here via seq * file lseek even if @ops->show() isn't implemented. */ ops = sysfs_file_ops(of->sd); if (ops->show) count = ops->show(kobj, of->sd->s_attr.attr, buf); else count = 0; sysfs_put_active(of->sd); mutex_unlock(&of->mutex); if (count < 0) return count; /* * The code works fine with PAGE_SIZE return but it's likely to * indicate truncated result or overflow in normal use cases. */ if (count >= (ssize_t)PAGE_SIZE) { print_symbol("fill_read_buffer: %s returned bad count\n", (unsigned long)ops->show); /* Try to struggle along */ count = PAGE_SIZE - 1; } seq_commit(sf, count); return 0; }
/* * Reads on sysfs are handled through seq_file, which takes care of hairy * details like buffering and seeking. The following function pipes * sysfs_ops->show() result through seq_file. */ static int sysfs_kf_seq_show(struct seq_file *sf, void *v) { struct kernfs_open_file *of = sf->private; struct kobject *kobj = of->kn->parent->priv; const struct sysfs_ops *ops = sysfs_file_ops(of->kn); ssize_t count; char *buf; /* acquire buffer and ensure that it's >= PAGE_SIZE and clear */ count = seq_get_buf(sf, &buf); if (count < PAGE_SIZE) { seq_commit(sf, -1); return 0; } memset(buf, 0, PAGE_SIZE); /* * Invoke show(). Control may reach here via seq file lseek even * if @ops->show() isn't implemented. */ if (ops->show) { count = ops->show(kobj, of->kn->priv, buf); if (count < 0) return count; } /* * The code works fine with PAGE_SIZE return but it's likely to * indicate truncated result or overflow in normal use cases. */ if (count >= (ssize_t)PAGE_SIZE) { print_symbol("fill_read_buffer: %s returned bad count\n", (unsigned long)ops->show); /* Try to struggle along */ count = PAGE_SIZE - 1; } seq_commit(sf, count); return 0; }
static inline void task_name(struct seq_file *m, struct task_struct *p) { char *buf; size_t size; char tcomm[sizeof(p->comm)]; int ret; get_task_comm(tcomm, p); seq_puts(m, "Name:\t"); size = seq_get_buf(m, &buf); ret = string_escape_str(tcomm, buf, size, ESCAPE_SPACE | ESCAPE_SPECIAL, "\n\\"); seq_commit(m, ret < size ? ret : -1); seq_putc(m, '\n'); }
static int mali_seq_internal_state_show(struct seq_file *seq_file, void *v) { u32 len = 0; u32 size; char *buf; size = seq_get_buf(seq_file, &buf); if (!size) { return -ENOMEM; } /* Create the internal state dump. */ len = snprintf(buf + len, size - len, "Mali device driver %s\n", SVN_REV_STRING); len += snprintf(buf + len, size - len, "License: %s\n\n", MALI_KERNEL_LINUX_LICENSE); len += _mali_kernel_core_dump_state(buf + len, size - len); seq_commit(seq_file, len); return 0; }
void proc_task_name(struct seq_file *m, struct task_struct *p, bool escape) { char *buf; size_t size; char tcomm[64]; int ret; if (p->flags & PF_WQ_WORKER) wq_worker_comm(tcomm, sizeof(tcomm), p); else __get_task_comm(tcomm, sizeof(tcomm), p); size = seq_get_buf(m, &buf); if (escape) { ret = string_escape_str(tcomm, buf, size, ESCAPE_SPACE | ESCAPE_SPECIAL, "\n\\"); if (ret >= size) ret = -1; } else { ret = strscpy(buf, tcomm, size); } seq_commit(m, ret); }