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

Configure Feed

Select the types of activity you want to include in your feed.

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 <hch@lst.de>:
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

+39 -17
+1 -1
fs/proc/cpuinfo.c
··· 19 19 static const struct proc_ops cpuinfo_proc_ops = { 20 20 .proc_flags = PROC_ENTRY_PERMANENT, 21 21 .proc_open = cpuinfo_open, 22 - .proc_read = seq_read, 22 + .proc_read_iter = seq_read_iter, 23 23 .proc_lseek = seq_lseek, 24 24 .proc_release = seq_release, 25 25 };
+2 -2
fs/proc/generic.c
··· 590 590 static const struct proc_ops proc_seq_ops = { 591 591 /* not permanent -- can call into arbitrary seq_operations */ 592 592 .proc_open = proc_seq_open, 593 - .proc_read = seq_read, 593 + .proc_read_iter = seq_read_iter, 594 594 .proc_lseek = seq_lseek, 595 595 .proc_release = proc_seq_release, 596 596 }; ··· 621 621 static const struct proc_ops proc_single_ops = { 622 622 /* not permanent -- can call into arbitrary ->single_show */ 623 623 .proc_open = proc_single_open, 624 - .proc_read = seq_read, 624 + .proc_read_iter = seq_read_iter, 625 625 .proc_lseek = seq_lseek, 626 626 .proc_release = single_release, 627 627 };
+2
fs/proc/inode.c
··· 597 597 .llseek = proc_reg_llseek, 598 598 .read_iter = proc_reg_read_iter, 599 599 .write = proc_reg_write, 600 + .splice_read = generic_file_splice_read, 600 601 .poll = proc_reg_poll, 601 602 .unlocked_ioctl = proc_reg_unlocked_ioctl, 602 603 .mmap = proc_reg_mmap, ··· 623 622 static const struct file_operations proc_iter_file_ops_compat = { 624 623 .llseek = proc_reg_llseek, 625 624 .read_iter = proc_reg_read_iter, 625 + .splice_read = generic_file_splice_read, 626 626 .write = proc_reg_write, 627 627 .poll = proc_reg_poll, 628 628 .unlocked_ioctl = proc_reg_unlocked_ioctl,
+1 -1
fs/proc/stat.c
··· 226 226 static const struct proc_ops stat_proc_ops = { 227 227 .proc_flags = PROC_ENTRY_PERMANENT, 228 228 .proc_open = stat_open, 229 - .proc_read = seq_read, 229 + .proc_read_iter = seq_read_iter, 230 230 .proc_lseek = seq_lseek, 231 231 .proc_release = single_release, 232 232 };
+32 -13
fs/seq_file.c
··· 18 18 #include <linux/mm.h> 19 19 #include <linux/printk.h> 20 20 #include <linux/string_helpers.h> 21 + #include <linux/uio.h> 21 22 22 23 #include <linux/uaccess.h> 23 24 #include <asm/page.h> ··· 147 146 */ 148 147 ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) 149 148 { 150 - struct seq_file *m = file->private_data; 149 + struct iovec iov = { .iov_base = buf, .iov_len = size}; 150 + struct kiocb kiocb; 151 + struct iov_iter iter; 152 + ssize_t ret; 153 + 154 + init_sync_kiocb(&kiocb, file); 155 + iov_iter_init(&iter, READ, &iov, 1, size); 156 + 157 + kiocb.ki_pos = *ppos; 158 + ret = seq_read_iter(&kiocb, &iter); 159 + *ppos = kiocb.ki_pos; 160 + return ret; 161 + } 162 + EXPORT_SYMBOL(seq_read); 163 + 164 + /* 165 + * Ready-made ->f_op->read_iter() 166 + */ 167 + ssize_t seq_read_iter(struct kiocb *iocb, struct iov_iter *iter) 168 + { 169 + struct seq_file *m = iocb->ki_filp->private_data; 170 + size_t size = iov_iter_count(iter); 151 171 size_t copied = 0; 152 172 size_t n; 153 173 void *p; ··· 180 158 * if request is to read from zero offset, reset iterator to first 181 159 * record as it might have been already advanced by previous requests 182 160 */ 183 - if (*ppos == 0) { 161 + if (iocb->ki_pos == 0) { 184 162 m->index = 0; 185 163 m->count = 0; 186 164 } 187 165 188 - /* Don't assume *ppos is where we left it */ 189 - if (unlikely(*ppos != m->read_pos)) { 190 - while ((err = traverse(m, *ppos)) == -EAGAIN) 166 + /* Don't assume ki_pos is where we left it */ 167 + if (unlikely(iocb->ki_pos != m->read_pos)) { 168 + while ((err = traverse(m, iocb->ki_pos)) == -EAGAIN) 191 169 ; 192 170 if (err) { 193 171 /* With prejudice... */ ··· 196 174 m->count = 0; 197 175 goto Done; 198 176 } else { 199 - m->read_pos = *ppos; 177 + m->read_pos = iocb->ki_pos; 200 178 } 201 179 } 202 180 ··· 209 187 /* if not empty - flush it first */ 210 188 if (m->count) { 211 189 n = min(m->count, size); 212 - err = copy_to_user(buf, m->buf + m->from, n); 213 - if (err) 190 + if (copy_to_iter(m->buf + m->from, n, iter) != n) 214 191 goto Efault; 215 192 m->count -= n; 216 193 m->from += n; 217 194 size -= n; 218 - buf += n; 219 195 copied += n; 220 196 if (!size) 221 197 goto Done; ··· 274 254 } 275 255 m->op->stop(m, p); 276 256 n = min(m->count, size); 277 - err = copy_to_user(buf, m->buf, n); 278 - if (err) 257 + if (copy_to_iter(m->buf, n, iter) != n) 279 258 goto Efault; 280 259 copied += n; 281 260 m->count -= n; ··· 283 264 if (!copied) 284 265 copied = err; 285 266 else { 286 - *ppos += copied; 267 + iocb->ki_pos += copied; 287 268 m->read_pos += copied; 288 269 } 289 270 mutex_unlock(&m->lock); ··· 295 276 err = -EFAULT; 296 277 goto Done; 297 278 } 298 - EXPORT_SYMBOL(seq_read); 279 + EXPORT_SYMBOL(seq_read_iter); 299 280 300 281 /** 301 282 * seq_lseek - ->llseek() method for sequential files.
+1
include/linux/seq_file.h
··· 107 107 char *mangle_path(char *s, const char *p, const char *esc); 108 108 int seq_open(struct file *, const struct seq_operations *); 109 109 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); 110 111 loff_t seq_lseek(struct file *, loff_t, int); 111 112 int seq_release(struct inode *, struct file *); 112 113 int seq_write(struct seq_file *seq, const void *data, size_t len);