Skip to content

Commit 6b2c4d5

Browse files
committed
Merge branch 'hch' (patches from Christoph)
Merge procfs splice read fixes from Christoph Hellwig: "Greg reported a problem due to the fact that Android tests use procfs files to test splice, which stopped working with the changes for set_fs() removal. This series adds read_iter support for seq_file, and uses those for various proc files using seq_file to restore splice read support" [ Side note: Christoph initially had a scripted "move everything over" patch, which looks fine, but I personally would prefer us to actively discourage splice() on random files. So this does just the minimal basic core set of proc file op conversions. For completeness, and in case people care, that script was sed -i -e 's/\.proc_read\(\s*=\s*\)seq_read/\.proc_read_iter\1seq_read_iter/g' but I'll wait and see if somebody has a strong argument for using splice on random small /proc files before I'd run it on the whole kernel. - Linus ] * emailed patches from Christoph Hellwig <[email protected]>: proc "seq files": switch to ->read_iter proc "single files": switch to ->read_iter proc/stat: switch to ->read_iter proc/cpuinfo: switch to ->read_iter proc: wire up generic_file_splice_read for iter ops seq_file: add seq_read_iter
2 parents 40be821 + b24c30c commit 6b2c4d5

File tree

6 files changed

+39
-17
lines changed

6 files changed

+39
-17
lines changed

fs/proc/cpuinfo.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ static int cpuinfo_open(struct inode *inode, struct file *file)
1919
static const struct proc_ops cpuinfo_proc_ops = {
2020
.proc_flags = PROC_ENTRY_PERMANENT,
2121
.proc_open = cpuinfo_open,
22-
.proc_read = seq_read,
22+
.proc_read_iter = seq_read_iter,
2323
.proc_lseek = seq_lseek,
2424
.proc_release = seq_release,
2525
};

fs/proc/generic.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -590,7 +590,7 @@ static int proc_seq_release(struct inode *inode, struct file *file)
590590
static const struct proc_ops proc_seq_ops = {
591591
/* not permanent -- can call into arbitrary seq_operations */
592592
.proc_open = proc_seq_open,
593-
.proc_read = seq_read,
593+
.proc_read_iter = seq_read_iter,
594594
.proc_lseek = seq_lseek,
595595
.proc_release = proc_seq_release,
596596
};
@@ -621,7 +621,7 @@ static int proc_single_open(struct inode *inode, struct file *file)
621621
static const struct proc_ops proc_single_ops = {
622622
/* not permanent -- can call into arbitrary ->single_show */
623623
.proc_open = proc_single_open,
624-
.proc_read = seq_read,
624+
.proc_read_iter = seq_read_iter,
625625
.proc_lseek = seq_lseek,
626626
.proc_release = single_release,
627627
};

fs/proc/inode.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,7 @@ static const struct file_operations proc_iter_file_ops = {
597597
.llseek = proc_reg_llseek,
598598
.read_iter = proc_reg_read_iter,
599599
.write = proc_reg_write,
600+
.splice_read = generic_file_splice_read,
600601
.poll = proc_reg_poll,
601602
.unlocked_ioctl = proc_reg_unlocked_ioctl,
602603
.mmap = proc_reg_mmap,
@@ -622,6 +623,7 @@ static const struct file_operations proc_reg_file_ops_compat = {
622623
static const struct file_operations proc_iter_file_ops_compat = {
623624
.llseek = proc_reg_llseek,
624625
.read_iter = proc_reg_read_iter,
626+
.splice_read = generic_file_splice_read,
625627
.write = proc_reg_write,
626628
.poll = proc_reg_poll,
627629
.unlocked_ioctl = proc_reg_unlocked_ioctl,

fs/proc/stat.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ static int stat_open(struct inode *inode, struct file *file)
226226
static const struct proc_ops stat_proc_ops = {
227227
.proc_flags = PROC_ENTRY_PERMANENT,
228228
.proc_open = stat_open,
229-
.proc_read = seq_read,
229+
.proc_read_iter = seq_read_iter,
230230
.proc_lseek = seq_lseek,
231231
.proc_release = single_release,
232232
};

fs/seq_file.c

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <linux/mm.h>
1919
#include <linux/printk.h>
2020
#include <linux/string_helpers.h>
21+
#include <linux/uio.h>
2122

2223
#include <linux/uaccess.h>
2324
#include <asm/page.h>
@@ -146,7 +147,28 @@ static int traverse(struct seq_file *m, loff_t offset)
146147
*/
147148
ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
148149
{
149-
struct seq_file *m = file->private_data;
150+
struct iovec iov = { .iov_base = buf, .iov_len = size};
151+
struct kiocb kiocb;
152+
struct iov_iter iter;
153+
ssize_t ret;
154+
155+
init_sync_kiocb(&kiocb, file);
156+
iov_iter_init(&iter, READ, &iov, 1, size);
157+
158+
kiocb.ki_pos = *ppos;
159+
ret = seq_read_iter(&kiocb, &iter);
160+
*ppos = kiocb.ki_pos;
161+
return ret;
162+
}
163+
EXPORT_SYMBOL(seq_read);
164+
165+
/*
166+
* Ready-made ->f_op->read_iter()
167+
*/
168+
ssize_t seq_read_iter(struct kiocb *iocb, struct iov_iter *iter)
169+
{
170+
struct seq_file *m = iocb->ki_filp->private_data;
171+
size_t size = iov_iter_count(iter);
150172
size_t copied = 0;
151173
size_t n;
152174
void *p;
@@ -158,14 +180,14 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
158180
* if request is to read from zero offset, reset iterator to first
159181
* record as it might have been already advanced by previous requests
160182
*/
161-
if (*ppos == 0) {
183+
if (iocb->ki_pos == 0) {
162184
m->index = 0;
163185
m->count = 0;
164186
}
165187

166-
/* Don't assume *ppos is where we left it */
167-
if (unlikely(*ppos != m->read_pos)) {
168-
while ((err = traverse(m, *ppos)) == -EAGAIN)
188+
/* Don't assume ki_pos is where we left it */
189+
if (unlikely(iocb->ki_pos != m->read_pos)) {
190+
while ((err = traverse(m, iocb->ki_pos)) == -EAGAIN)
169191
;
170192
if (err) {
171193
/* With prejudice... */
@@ -174,7 +196,7 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
174196
m->count = 0;
175197
goto Done;
176198
} else {
177-
m->read_pos = *ppos;
199+
m->read_pos = iocb->ki_pos;
178200
}
179201
}
180202

@@ -187,13 +209,11 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
187209
/* if not empty - flush it first */
188210
if (m->count) {
189211
n = min(m->count, size);
190-
err = copy_to_user(buf, m->buf + m->from, n);
191-
if (err)
212+
if (copy_to_iter(m->buf + m->from, n, iter) != n)
192213
goto Efault;
193214
m->count -= n;
194215
m->from += n;
195216
size -= n;
196-
buf += n;
197217
copied += n;
198218
if (!size)
199219
goto Done;
@@ -254,8 +274,7 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
254274
}
255275
m->op->stop(m, p);
256276
n = min(m->count, size);
257-
err = copy_to_user(buf, m->buf, n);
258-
if (err)
277+
if (copy_to_iter(m->buf, n, iter) != n)
259278
goto Efault;
260279
copied += n;
261280
m->count -= n;
@@ -264,7 +283,7 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
264283
if (!copied)
265284
copied = err;
266285
else {
267-
*ppos += copied;
286+
iocb->ki_pos += copied;
268287
m->read_pos += copied;
269288
}
270289
mutex_unlock(&m->lock);
@@ -276,7 +295,7 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
276295
err = -EFAULT;
277296
goto Done;
278297
}
279-
EXPORT_SYMBOL(seq_read);
298+
EXPORT_SYMBOL(seq_read_iter);
280299

281300
/**
282301
* seq_lseek - ->llseek() method for sequential files.

include/linux/seq_file.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ void seq_pad(struct seq_file *m, char c);
107107
char *mangle_path(char *s, const char *p, const char *esc);
108108
int seq_open(struct file *, const struct seq_operations *);
109109
ssize_t seq_read(struct file *, char __user *, size_t, loff_t *);
110+
ssize_t seq_read_iter(struct kiocb *iocb, struct iov_iter *iter);
110111
loff_t seq_lseek(struct file *, loff_t, int);
111112
int seq_release(struct inode *, struct file *);
112113
int seq_write(struct seq_file *seq, const void *data, size_t len);

0 commit comments

Comments
 (0)