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

proc: mandate ->proc_lseek in "struct proc_ops"

Now that proc_ops are separate from file_operations and other operations
it easy to check all instances to have ->proc_lseek hook and remove check
in main code.

Note:
nonseekable_open() files naturally don't require ->proc_lseek.

Garbage collect pde_lseek() function.

[adobriyan@gmail.com: smoke test lseek()]
Link: https://lkml.kernel.org/r/YG4OIhChOrVTPgdN@localhost.localdomain

Link: https://lkml.kernel.org/r/YFYX0Bzwxlc7aBa/@localhost.localdomain
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Alexey Dobriyan and committed by
Linus Torvalds
d4455fac b793cd9a

+9 -13
+1
drivers/isdn/capi/kcapi_proc.c
··· 201 201 202 202 static const struct proc_ops empty_proc_ops = { 203 203 .proc_read = empty_read, 204 + .proc_lseek = default_llseek, 204 205 }; 205 206 206 207 // ---------------------------------------------------------------------------
+1
drivers/net/wireless/intersil/hostap/hostap_proc.c
··· 227 227 228 228 static const struct proc_ops prism2_aux_dump_proc_ops = { 229 229 .proc_read = prism2_aux_dump_proc_no_read, 230 + .proc_lseek = default_llseek, 230 231 }; 231 232 232 233
+1
drivers/scsi/esas2r/esas2r_main.c
··· 616 616 }; 617 617 618 618 static const struct proc_ops esas2r_proc_ops = { 619 + .proc_lseek = default_llseek, 619 620 .proc_ioctl = esas2r_proc_ioctl, 620 621 #ifdef CONFIG_COMPAT 621 622 .proc_compat_ioctl = compat_ptr_ioctl,
+2 -12
fs/proc/inode.c
··· 273 273 spin_unlock(&de->pde_unload_lock); 274 274 } 275 275 276 - static loff_t pde_lseek(struct proc_dir_entry *pde, struct file *file, loff_t offset, int whence) 277 - { 278 - typeof_member(struct proc_ops, proc_lseek) lseek; 279 - 280 - lseek = pde->proc_ops->proc_lseek; 281 - if (!lseek) 282 - lseek = default_llseek; 283 - return lseek(file, offset, whence); 284 - } 285 - 286 276 static loff_t proc_reg_llseek(struct file *file, loff_t offset, int whence) 287 277 { 288 278 struct proc_dir_entry *pde = PDE(file_inode(file)); 289 279 loff_t rv = -EINVAL; 290 280 291 281 if (pde_is_permanent(pde)) { 292 - return pde_lseek(pde, file, offset, whence); 282 + return pde->proc_ops->proc_lseek(file, offset, whence); 293 283 } else if (use_pde(pde)) { 294 - rv = pde_lseek(pde, file, offset, whence); 284 + rv = pde->proc_ops->proc_lseek(file, offset, whence); 295 285 unuse_pde(pde); 296 286 } 297 287 return rv;
+1
include/linux/proc_fs.h
··· 32 32 ssize_t (*proc_read)(struct file *, char __user *, size_t, loff_t *); 33 33 ssize_t (*proc_read_iter)(struct kiocb *, struct iov_iter *); 34 34 ssize_t (*proc_write)(struct file *, const char __user *, size_t, loff_t *); 35 + /* mandatory unless nonseekable_open() or equivalent is used */ 35 36 loff_t (*proc_lseek)(struct file *, loff_t, int); 36 37 int (*proc_release)(struct inode *, struct file *); 37 38 __poll_t (*proc_poll)(struct file *, struct poll_table_struct *);
+3 -1
tools/testing/selftests/proc/read.c
··· 14 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 15 */ 16 16 // Test 17 - // 1) read of every file in /proc 17 + // 1) read and lseek on every file in /proc 18 18 // 2) readlink of every symlink in /proc 19 19 // 3) recursively (1) + (2) for every directory in /proc 20 20 // 4) write to /proc/*/clear_refs and /proc/*/task/*/clear_refs ··· 45 45 fd = openat(dirfd(d), filename, O_RDONLY|O_NONBLOCK); 46 46 if (fd == -1) 47 47 return; 48 + /* struct proc_ops::proc_lseek is mandatory if file is seekable. */ 49 + (void)lseek(fd, 0, SEEK_SET); 48 50 rv = read(fd, buf, sizeof(buf)); 49 51 assert((0 <= rv && rv <= sizeof(buf)) || rv == -1); 50 52 close(fd);