| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * fs/kernfs/file.c - kernfs file implementation |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (c) 2001-3 Patrick Mochel |
|---|
| 5 | 6 | * Copyright (c) 2007 SUSE Linux Products GmbH |
|---|
| 6 | 7 | * Copyright (c) 2007, 2013 Tejun Heo <tj@kernel.org> |
|---|
| 7 | | - * |
|---|
| 8 | | - * This file is released under the GPLv2. |
|---|
| 9 | 8 | */ |
|---|
| 10 | 9 | |
|---|
| 11 | 10 | #include <linux/fs.h> |
|---|
| .. | .. |
|---|
| 15 | 14 | #include <linux/pagemap.h> |
|---|
| 16 | 15 | #include <linux/sched/mm.h> |
|---|
| 17 | 16 | #include <linux/fsnotify.h> |
|---|
| 17 | +#include <linux/uio.h> |
|---|
| 18 | 18 | |
|---|
| 19 | 19 | #include "kernfs-internal.h" |
|---|
| 20 | 20 | |
|---|
| .. | .. |
|---|
| 181 | 181 | * it difficult to use seq_file. Implement simplistic custom buffering for |
|---|
| 182 | 182 | * bin files. |
|---|
| 183 | 183 | */ |
|---|
| 184 | | -static ssize_t kernfs_file_direct_read(struct kernfs_open_file *of, |
|---|
| 185 | | - char __user *user_buf, size_t count, |
|---|
| 186 | | - loff_t *ppos) |
|---|
| 184 | +static ssize_t kernfs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter) |
|---|
| 187 | 185 | { |
|---|
| 188 | | - ssize_t len = min_t(size_t, count, PAGE_SIZE); |
|---|
| 186 | + struct kernfs_open_file *of = kernfs_of(iocb->ki_filp); |
|---|
| 187 | + ssize_t len = min_t(size_t, iov_iter_count(iter), PAGE_SIZE); |
|---|
| 189 | 188 | const struct kernfs_ops *ops; |
|---|
| 190 | 189 | char *buf; |
|---|
| 191 | 190 | |
|---|
| .. | .. |
|---|
| 211 | 210 | of->event = atomic_read(&of->kn->attr.open->event); |
|---|
| 212 | 211 | ops = kernfs_ops(of->kn); |
|---|
| 213 | 212 | if (ops->read) |
|---|
| 214 | | - len = ops->read(of, buf, len, *ppos); |
|---|
| 213 | + len = ops->read(of, buf, len, iocb->ki_pos); |
|---|
| 215 | 214 | else |
|---|
| 216 | 215 | len = -EINVAL; |
|---|
| 217 | 216 | |
|---|
| .. | .. |
|---|
| 221 | 220 | if (len < 0) |
|---|
| 222 | 221 | goto out_free; |
|---|
| 223 | 222 | |
|---|
| 224 | | - if (copy_to_user(user_buf, buf, len)) { |
|---|
| 223 | + if (copy_to_iter(buf, len, iter) != len) { |
|---|
| 225 | 224 | len = -EFAULT; |
|---|
| 226 | 225 | goto out_free; |
|---|
| 227 | 226 | } |
|---|
| 228 | 227 | |
|---|
| 229 | | - *ppos += len; |
|---|
| 228 | + iocb->ki_pos += len; |
|---|
| 230 | 229 | |
|---|
| 231 | 230 | out_free: |
|---|
| 232 | 231 | if (buf == of->prealloc_buf) |
|---|
| .. | .. |
|---|
| 236 | 235 | return len; |
|---|
| 237 | 236 | } |
|---|
| 238 | 237 | |
|---|
| 239 | | -/** |
|---|
| 240 | | - * kernfs_fop_read - kernfs vfs read callback |
|---|
| 241 | | - * @file: file pointer |
|---|
| 242 | | - * @user_buf: data to write |
|---|
| 243 | | - * @count: number of bytes |
|---|
| 244 | | - * @ppos: starting offset |
|---|
| 245 | | - */ |
|---|
| 246 | | -static ssize_t kernfs_fop_read(struct file *file, char __user *user_buf, |
|---|
| 247 | | - size_t count, loff_t *ppos) |
|---|
| 238 | +static ssize_t kernfs_fop_read_iter(struct kiocb *iocb, struct iov_iter *iter) |
|---|
| 248 | 239 | { |
|---|
| 249 | | - struct kernfs_open_file *of = kernfs_of(file); |
|---|
| 250 | | - |
|---|
| 251 | | - if (of->kn->flags & KERNFS_HAS_SEQ_SHOW) |
|---|
| 252 | | - return seq_read(file, user_buf, count, ppos); |
|---|
| 253 | | - else |
|---|
| 254 | | - return kernfs_file_direct_read(of, user_buf, count, ppos); |
|---|
| 240 | + if (kernfs_of(iocb->ki_filp)->kn->flags & KERNFS_HAS_SEQ_SHOW) |
|---|
| 241 | + return seq_read_iter(iocb, iter); |
|---|
| 242 | + return kernfs_file_read_iter(iocb, iter); |
|---|
| 255 | 243 | } |
|---|
| 256 | 244 | |
|---|
| 257 | | -/** |
|---|
| 258 | | - * kernfs_fop_write - kernfs vfs write callback |
|---|
| 259 | | - * @file: file pointer |
|---|
| 260 | | - * @user_buf: data to write |
|---|
| 261 | | - * @count: number of bytes |
|---|
| 262 | | - * @ppos: starting offset |
|---|
| 263 | | - * |
|---|
| 245 | +/* |
|---|
| 264 | 246 | * Copy data in from userland and pass it to the matching kernfs write |
|---|
| 265 | 247 | * operation. |
|---|
| 266 | 248 | * |
|---|
| .. | .. |
|---|
| 270 | 252 | * modify only the the value you're changing, then write entire buffer |
|---|
| 271 | 253 | * back. |
|---|
| 272 | 254 | */ |
|---|
| 273 | | -static ssize_t kernfs_fop_write(struct file *file, const char __user *user_buf, |
|---|
| 274 | | - size_t count, loff_t *ppos) |
|---|
| 255 | +static ssize_t kernfs_fop_write_iter(struct kiocb *iocb, struct iov_iter *iter) |
|---|
| 275 | 256 | { |
|---|
| 276 | | - struct kernfs_open_file *of = kernfs_of(file); |
|---|
| 257 | + struct kernfs_open_file *of = kernfs_of(iocb->ki_filp); |
|---|
| 258 | + ssize_t len = iov_iter_count(iter); |
|---|
| 277 | 259 | const struct kernfs_ops *ops; |
|---|
| 278 | | - ssize_t len; |
|---|
| 279 | 260 | char *buf; |
|---|
| 280 | 261 | |
|---|
| 281 | 262 | if (of->atomic_write_len) { |
|---|
| 282 | | - len = count; |
|---|
| 283 | 263 | if (len > of->atomic_write_len) |
|---|
| 284 | 264 | return -E2BIG; |
|---|
| 285 | 265 | } else { |
|---|
| 286 | | - len = min_t(size_t, count, PAGE_SIZE); |
|---|
| 266 | + len = min_t(size_t, len, PAGE_SIZE); |
|---|
| 287 | 267 | } |
|---|
| 288 | 268 | |
|---|
| 289 | 269 | buf = of->prealloc_buf; |
|---|
| .. | .. |
|---|
| 294 | 274 | if (!buf) |
|---|
| 295 | 275 | return -ENOMEM; |
|---|
| 296 | 276 | |
|---|
| 297 | | - if (copy_from_user(buf, user_buf, len)) { |
|---|
| 277 | + if (copy_from_iter(buf, len, iter) != len) { |
|---|
| 298 | 278 | len = -EFAULT; |
|---|
| 299 | 279 | goto out_free; |
|---|
| 300 | 280 | } |
|---|
| .. | .. |
|---|
| 313 | 293 | |
|---|
| 314 | 294 | ops = kernfs_ops(of->kn); |
|---|
| 315 | 295 | if (ops->write) |
|---|
| 316 | | - len = ops->write(of, buf, len, *ppos); |
|---|
| 296 | + len = ops->write(of, buf, len, iocb->ki_pos); |
|---|
| 317 | 297 | else |
|---|
| 318 | 298 | len = -EINVAL; |
|---|
| 319 | 299 | |
|---|
| .. | .. |
|---|
| 321 | 301 | mutex_unlock(&of->mutex); |
|---|
| 322 | 302 | |
|---|
| 323 | 303 | if (len > 0) |
|---|
| 324 | | - *ppos += len; |
|---|
| 304 | + iocb->ki_pos += len; |
|---|
| 325 | 305 | |
|---|
| 326 | 306 | out_free: |
|---|
| 327 | 307 | if (buf == of->prealloc_buf) |
|---|
| .. | .. |
|---|
| 653 | 633 | * The following is done to give a different lockdep key to |
|---|
| 654 | 634 | * @of->mutex for files which implement mmap. This is a rather |
|---|
| 655 | 635 | * crude way to avoid false positive lockdep warning around |
|---|
| 656 | | - * mm->mmap_sem - mmap nests @of->mutex under mm->mmap_sem and |
|---|
| 636 | + * mm->mmap_lock - mmap nests @of->mutex under mm->mmap_lock and |
|---|
| 657 | 637 | * reading /sys/block/sda/trace/act_mask grabs sr_mutex, under |
|---|
| 658 | | - * which mm->mmap_sem nests, while holding @of->mutex. As each |
|---|
| 638 | + * which mm->mmap_lock nests, while holding @of->mutex. As each |
|---|
| 659 | 639 | * open file has a separate mutex, it's okay as long as those don't |
|---|
| 660 | 640 | * happen on the same file. At this point, we can't easily give |
|---|
| 661 | 641 | * each file a separate locking class. Let's differentiate on |
|---|
| .. | .. |
|---|
| 674 | 654 | |
|---|
| 675 | 655 | /* |
|---|
| 676 | 656 | * Write path needs to atomic_write_len outside active reference. |
|---|
| 677 | | - * Cache it in open_file. See kernfs_fop_write() for details. |
|---|
| 657 | + * Cache it in open_file. See kernfs_fop_write_iter() for details. |
|---|
| 678 | 658 | */ |
|---|
| 679 | 659 | of->atomic_write_len = ops->atomic_write_len; |
|---|
| 680 | 660 | |
|---|
| .. | .. |
|---|
| 884 | 864 | |
|---|
| 885 | 865 | list_for_each_entry(info, &kernfs_root(kn)->supers, node) { |
|---|
| 886 | 866 | struct kernfs_node *parent; |
|---|
| 867 | + struct inode *p_inode = NULL; |
|---|
| 887 | 868 | struct inode *inode; |
|---|
| 869 | + struct qstr name; |
|---|
| 888 | 870 | |
|---|
| 889 | 871 | /* |
|---|
| 890 | 872 | * We want fsnotify_modify() on @kn but as the |
|---|
| .. | .. |
|---|
| 892 | 874 | * have the matching @file available. Look up the inodes |
|---|
| 893 | 875 | * and generate the events manually. |
|---|
| 894 | 876 | */ |
|---|
| 895 | | - inode = ilookup(info->sb, kn->id.ino); |
|---|
| 877 | + inode = ilookup(info->sb, kernfs_ino(kn)); |
|---|
| 896 | 878 | if (!inode) |
|---|
| 897 | 879 | continue; |
|---|
| 898 | 880 | |
|---|
| 881 | + name = (struct qstr)QSTR_INIT(kn->name, strlen(kn->name)); |
|---|
| 899 | 882 | parent = kernfs_get_parent(kn); |
|---|
| 900 | 883 | if (parent) { |
|---|
| 901 | | - struct inode *p_inode; |
|---|
| 902 | | - |
|---|
| 903 | | - p_inode = ilookup(info->sb, parent->id.ino); |
|---|
| 884 | + p_inode = ilookup(info->sb, kernfs_ino(parent)); |
|---|
| 904 | 885 | if (p_inode) { |
|---|
| 905 | | - fsnotify(p_inode, FS_MODIFY | FS_EVENT_ON_CHILD, |
|---|
| 906 | | - inode, FSNOTIFY_EVENT_INODE, kn->name, 0); |
|---|
| 886 | + fsnotify(FS_MODIFY | FS_EVENT_ON_CHILD, |
|---|
| 887 | + inode, FSNOTIFY_EVENT_INODE, |
|---|
| 888 | + p_inode, &name, inode, 0); |
|---|
| 907 | 889 | iput(p_inode); |
|---|
| 908 | 890 | } |
|---|
| 909 | 891 | |
|---|
| 910 | 892 | kernfs_put(parent); |
|---|
| 911 | 893 | } |
|---|
| 912 | 894 | |
|---|
| 913 | | - fsnotify(inode, FS_MODIFY, inode, FSNOTIFY_EVENT_INODE, |
|---|
| 914 | | - kn->name, 0); |
|---|
| 895 | + if (!p_inode) |
|---|
| 896 | + fsnotify_inode(inode, FS_MODIFY); |
|---|
| 897 | + |
|---|
| 915 | 898 | iput(inode); |
|---|
| 916 | 899 | } |
|---|
| 917 | 900 | |
|---|
| .. | .. |
|---|
| 958 | 941 | EXPORT_SYMBOL_GPL(kernfs_notify); |
|---|
| 959 | 942 | |
|---|
| 960 | 943 | const struct file_operations kernfs_file_fops = { |
|---|
| 961 | | - .read = kernfs_fop_read, |
|---|
| 962 | | - .write = kernfs_fop_write, |
|---|
| 944 | + .read_iter = kernfs_fop_read_iter, |
|---|
| 945 | + .write_iter = kernfs_fop_write_iter, |
|---|
| 963 | 946 | .llseek = generic_file_llseek, |
|---|
| 964 | 947 | .mmap = kernfs_fop_mmap, |
|---|
| 965 | 948 | .open = kernfs_fop_open, |
|---|
| 966 | 949 | .release = kernfs_fop_release, |
|---|
| 967 | 950 | .poll = kernfs_fop_poll, |
|---|
| 968 | 951 | .fsync = noop_fsync, |
|---|
| 952 | + .splice_read = generic_file_splice_read, |
|---|
| 953 | + .splice_write = iter_file_splice_write, |
|---|
| 969 | 954 | }; |
|---|
| 970 | 955 | |
|---|
| 971 | 956 | /** |
|---|
| .. | .. |
|---|
| 1009 | 994 | |
|---|
| 1010 | 995 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
|---|
| 1011 | 996 | if (key) { |
|---|
| 1012 | | - lockdep_init_map(&kn->dep_map, "kn->count", key, 0); |
|---|
| 997 | + lockdep_init_map(&kn->dep_map, "kn->active", key, 0); |
|---|
| 1013 | 998 | kn->flags |= KERNFS_LOCKDEP; |
|---|
| 1014 | 999 | } |
|---|
| 1015 | 1000 | #endif |
|---|