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