| .. | .. | 
|---|
|  | 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 | 
|---|