xref: /OK3568_Linux_fs/kernel/fs/ioctl.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  *  linux/fs/ioctl.c
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  *  Copyright (C) 1991, 1992  Linus Torvalds
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/syscalls.h>
9*4882a593Smuzhiyun #include <linux/mm.h>
10*4882a593Smuzhiyun #include <linux/capability.h>
11*4882a593Smuzhiyun #include <linux/compat.h>
12*4882a593Smuzhiyun #include <linux/file.h>
13*4882a593Smuzhiyun #include <linux/fs.h>
14*4882a593Smuzhiyun #include <linux/security.h>
15*4882a593Smuzhiyun #include <linux/export.h>
16*4882a593Smuzhiyun #include <linux/uaccess.h>
17*4882a593Smuzhiyun #include <linux/writeback.h>
18*4882a593Smuzhiyun #include <linux/buffer_head.h>
19*4882a593Smuzhiyun #include <linux/falloc.h>
20*4882a593Smuzhiyun #include <linux/sched/signal.h>
21*4882a593Smuzhiyun #include <linux/fiemap.h>
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #include "internal.h"
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun #include <asm/ioctls.h>
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun /* So that the fiemap access checks can't overflow on 32 bit machines. */
28*4882a593Smuzhiyun #define FIEMAP_MAX_EXTENTS	(UINT_MAX / sizeof(struct fiemap_extent))
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun /**
31*4882a593Smuzhiyun  * vfs_ioctl - call filesystem specific ioctl methods
32*4882a593Smuzhiyun  * @filp:	open file to invoke ioctl method on
33*4882a593Smuzhiyun  * @cmd:	ioctl command to execute
34*4882a593Smuzhiyun  * @arg:	command-specific argument for ioctl
35*4882a593Smuzhiyun  *
36*4882a593Smuzhiyun  * Invokes filesystem specific ->unlocked_ioctl, if one exists; otherwise
37*4882a593Smuzhiyun  * returns -ENOTTY.
38*4882a593Smuzhiyun  *
39*4882a593Smuzhiyun  * Returns 0 on success, -errno on error.
40*4882a593Smuzhiyun  */
vfs_ioctl(struct file * filp,unsigned int cmd,unsigned long arg)41*4882a593Smuzhiyun long vfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
42*4882a593Smuzhiyun {
43*4882a593Smuzhiyun 	int error = -ENOTTY;
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun 	if (!filp->f_op->unlocked_ioctl)
46*4882a593Smuzhiyun 		goto out;
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun 	error = filp->f_op->unlocked_ioctl(filp, cmd, arg);
49*4882a593Smuzhiyun 	if (error == -ENOIOCTLCMD)
50*4882a593Smuzhiyun 		error = -ENOTTY;
51*4882a593Smuzhiyun  out:
52*4882a593Smuzhiyun 	return error;
53*4882a593Smuzhiyun }
54*4882a593Smuzhiyun EXPORT_SYMBOL(vfs_ioctl);
55*4882a593Smuzhiyun 
ioctl_fibmap(struct file * filp,int __user * p)56*4882a593Smuzhiyun static int ioctl_fibmap(struct file *filp, int __user *p)
57*4882a593Smuzhiyun {
58*4882a593Smuzhiyun 	struct inode *inode = file_inode(filp);
59*4882a593Smuzhiyun 	struct super_block *sb = inode->i_sb;
60*4882a593Smuzhiyun 	int error, ur_block;
61*4882a593Smuzhiyun 	sector_t block;
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 	if (!capable(CAP_SYS_RAWIO))
64*4882a593Smuzhiyun 		return -EPERM;
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun 	error = get_user(ur_block, p);
67*4882a593Smuzhiyun 	if (error)
68*4882a593Smuzhiyun 		return error;
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun 	if (ur_block < 0)
71*4882a593Smuzhiyun 		return -EINVAL;
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun 	block = ur_block;
74*4882a593Smuzhiyun 	error = bmap(inode, &block);
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun 	if (block > INT_MAX) {
77*4882a593Smuzhiyun 		error = -ERANGE;
78*4882a593Smuzhiyun 		pr_warn_ratelimited("[%s/%d] FS: %s File: %pD4 would truncate fibmap result\n",
79*4882a593Smuzhiyun 				    current->comm, task_pid_nr(current),
80*4882a593Smuzhiyun 				    sb->s_id, filp);
81*4882a593Smuzhiyun 	}
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 	if (error)
84*4882a593Smuzhiyun 		ur_block = 0;
85*4882a593Smuzhiyun 	else
86*4882a593Smuzhiyun 		ur_block = block;
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 	if (put_user(ur_block, p))
89*4882a593Smuzhiyun 		error = -EFAULT;
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun 	return error;
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun /**
95*4882a593Smuzhiyun  * fiemap_fill_next_extent - Fiemap helper function
96*4882a593Smuzhiyun  * @fieinfo:	Fiemap context passed into ->fiemap
97*4882a593Smuzhiyun  * @logical:	Extent logical start offset, in bytes
98*4882a593Smuzhiyun  * @phys:	Extent physical start offset, in bytes
99*4882a593Smuzhiyun  * @len:	Extent length, in bytes
100*4882a593Smuzhiyun  * @flags:	FIEMAP_EXTENT flags that describe this extent
101*4882a593Smuzhiyun  *
102*4882a593Smuzhiyun  * Called from file system ->fiemap callback. Will populate extent
103*4882a593Smuzhiyun  * info as passed in via arguments and copy to user memory. On
104*4882a593Smuzhiyun  * success, extent count on fieinfo is incremented.
105*4882a593Smuzhiyun  *
106*4882a593Smuzhiyun  * Returns 0 on success, -errno on error, 1 if this was the last
107*4882a593Smuzhiyun  * extent that will fit in user array.
108*4882a593Smuzhiyun  */
109*4882a593Smuzhiyun #define SET_UNKNOWN_FLAGS	(FIEMAP_EXTENT_DELALLOC)
110*4882a593Smuzhiyun #define SET_NO_UNMOUNTED_IO_FLAGS	(FIEMAP_EXTENT_DATA_ENCRYPTED)
111*4882a593Smuzhiyun #define SET_NOT_ALIGNED_FLAGS	(FIEMAP_EXTENT_DATA_TAIL|FIEMAP_EXTENT_DATA_INLINE)
fiemap_fill_next_extent(struct fiemap_extent_info * fieinfo,u64 logical,u64 phys,u64 len,u32 flags)112*4882a593Smuzhiyun int fiemap_fill_next_extent(struct fiemap_extent_info *fieinfo, u64 logical,
113*4882a593Smuzhiyun 			    u64 phys, u64 len, u32 flags)
114*4882a593Smuzhiyun {
115*4882a593Smuzhiyun 	struct fiemap_extent extent;
116*4882a593Smuzhiyun 	struct fiemap_extent __user *dest = fieinfo->fi_extents_start;
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun 	/* only count the extents */
119*4882a593Smuzhiyun 	if (fieinfo->fi_extents_max == 0) {
120*4882a593Smuzhiyun 		fieinfo->fi_extents_mapped++;
121*4882a593Smuzhiyun 		return (flags & FIEMAP_EXTENT_LAST) ? 1 : 0;
122*4882a593Smuzhiyun 	}
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun 	if (fieinfo->fi_extents_mapped >= fieinfo->fi_extents_max)
125*4882a593Smuzhiyun 		return 1;
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun 	if (flags & SET_UNKNOWN_FLAGS)
128*4882a593Smuzhiyun 		flags |= FIEMAP_EXTENT_UNKNOWN;
129*4882a593Smuzhiyun 	if (flags & SET_NO_UNMOUNTED_IO_FLAGS)
130*4882a593Smuzhiyun 		flags |= FIEMAP_EXTENT_ENCODED;
131*4882a593Smuzhiyun 	if (flags & SET_NOT_ALIGNED_FLAGS)
132*4882a593Smuzhiyun 		flags |= FIEMAP_EXTENT_NOT_ALIGNED;
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun 	memset(&extent, 0, sizeof(extent));
135*4882a593Smuzhiyun 	extent.fe_logical = logical;
136*4882a593Smuzhiyun 	extent.fe_physical = phys;
137*4882a593Smuzhiyun 	extent.fe_length = len;
138*4882a593Smuzhiyun 	extent.fe_flags = flags;
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun 	dest += fieinfo->fi_extents_mapped;
141*4882a593Smuzhiyun 	if (copy_to_user(dest, &extent, sizeof(extent)))
142*4882a593Smuzhiyun 		return -EFAULT;
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 	fieinfo->fi_extents_mapped++;
145*4882a593Smuzhiyun 	if (fieinfo->fi_extents_mapped == fieinfo->fi_extents_max)
146*4882a593Smuzhiyun 		return 1;
147*4882a593Smuzhiyun 	return (flags & FIEMAP_EXTENT_LAST) ? 1 : 0;
148*4882a593Smuzhiyun }
149*4882a593Smuzhiyun EXPORT_SYMBOL_NS(fiemap_fill_next_extent, ANDROID_GKI_VFS_EXPORT_ONLY);
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun /**
152*4882a593Smuzhiyun  * fiemap_prep - check validity of requested flags for fiemap
153*4882a593Smuzhiyun  * @inode:	Inode to operate on
154*4882a593Smuzhiyun  * @fieinfo:	Fiemap context passed into ->fiemap
155*4882a593Smuzhiyun  * @start:	Start of the mapped range
156*4882a593Smuzhiyun  * @len:	Length of the mapped range, can be truncated by this function.
157*4882a593Smuzhiyun  * @supported_flags:	Set of fiemap flags that the file system understands
158*4882a593Smuzhiyun  *
159*4882a593Smuzhiyun  * This function must be called from each ->fiemap instance to validate the
160*4882a593Smuzhiyun  * fiemap request against the file system parameters.
161*4882a593Smuzhiyun  *
162*4882a593Smuzhiyun  * Returns 0 on success, or a negative error on failure.
163*4882a593Smuzhiyun  */
fiemap_prep(struct inode * inode,struct fiemap_extent_info * fieinfo,u64 start,u64 * len,u32 supported_flags)164*4882a593Smuzhiyun int fiemap_prep(struct inode *inode, struct fiemap_extent_info *fieinfo,
165*4882a593Smuzhiyun 		u64 start, u64 *len, u32 supported_flags)
166*4882a593Smuzhiyun {
167*4882a593Smuzhiyun 	u64 maxbytes = inode->i_sb->s_maxbytes;
168*4882a593Smuzhiyun 	u32 incompat_flags;
169*4882a593Smuzhiyun 	int ret = 0;
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun 	if (*len == 0)
172*4882a593Smuzhiyun 		return -EINVAL;
173*4882a593Smuzhiyun 	if (start >= maxbytes)
174*4882a593Smuzhiyun 		return -EFBIG;
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun 	/*
177*4882a593Smuzhiyun 	 * Shrink request scope to what the fs can actually handle.
178*4882a593Smuzhiyun 	 */
179*4882a593Smuzhiyun 	if (*len > maxbytes || (maxbytes - *len) < start)
180*4882a593Smuzhiyun 		*len = maxbytes - start;
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 	supported_flags |= FIEMAP_FLAG_SYNC;
183*4882a593Smuzhiyun 	supported_flags &= FIEMAP_FLAGS_COMPAT;
184*4882a593Smuzhiyun 	incompat_flags = fieinfo->fi_flags & ~supported_flags;
185*4882a593Smuzhiyun 	if (incompat_flags) {
186*4882a593Smuzhiyun 		fieinfo->fi_flags = incompat_flags;
187*4882a593Smuzhiyun 		return -EBADR;
188*4882a593Smuzhiyun 	}
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun 	if (fieinfo->fi_flags & FIEMAP_FLAG_SYNC)
191*4882a593Smuzhiyun 		ret = filemap_write_and_wait(inode->i_mapping);
192*4882a593Smuzhiyun 	return ret;
193*4882a593Smuzhiyun }
194*4882a593Smuzhiyun EXPORT_SYMBOL_NS(fiemap_prep, ANDROID_GKI_VFS_EXPORT_ONLY);
195*4882a593Smuzhiyun 
ioctl_fiemap(struct file * filp,struct fiemap __user * ufiemap)196*4882a593Smuzhiyun static int ioctl_fiemap(struct file *filp, struct fiemap __user *ufiemap)
197*4882a593Smuzhiyun {
198*4882a593Smuzhiyun 	struct fiemap fiemap;
199*4882a593Smuzhiyun 	struct fiemap_extent_info fieinfo = { 0, };
200*4882a593Smuzhiyun 	struct inode *inode = file_inode(filp);
201*4882a593Smuzhiyun 	int error;
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun 	if (!inode->i_op->fiemap)
204*4882a593Smuzhiyun 		return -EOPNOTSUPP;
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun 	if (copy_from_user(&fiemap, ufiemap, sizeof(fiemap)))
207*4882a593Smuzhiyun 		return -EFAULT;
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 	if (fiemap.fm_extent_count > FIEMAP_MAX_EXTENTS)
210*4882a593Smuzhiyun 		return -EINVAL;
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 	fieinfo.fi_flags = fiemap.fm_flags;
213*4882a593Smuzhiyun 	fieinfo.fi_extents_max = fiemap.fm_extent_count;
214*4882a593Smuzhiyun 	fieinfo.fi_extents_start = ufiemap->fm_extents;
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun 	error = inode->i_op->fiemap(inode, &fieinfo, fiemap.fm_start,
217*4882a593Smuzhiyun 			fiemap.fm_length);
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun 	fiemap.fm_flags = fieinfo.fi_flags;
220*4882a593Smuzhiyun 	fiemap.fm_mapped_extents = fieinfo.fi_extents_mapped;
221*4882a593Smuzhiyun 	if (copy_to_user(ufiemap, &fiemap, sizeof(fiemap)))
222*4882a593Smuzhiyun 		error = -EFAULT;
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun 	return error;
225*4882a593Smuzhiyun }
226*4882a593Smuzhiyun 
ioctl_file_clone(struct file * dst_file,unsigned long srcfd,u64 off,u64 olen,u64 destoff)227*4882a593Smuzhiyun static long ioctl_file_clone(struct file *dst_file, unsigned long srcfd,
228*4882a593Smuzhiyun 			     u64 off, u64 olen, u64 destoff)
229*4882a593Smuzhiyun {
230*4882a593Smuzhiyun 	struct fd src_file = fdget(srcfd);
231*4882a593Smuzhiyun 	loff_t cloned;
232*4882a593Smuzhiyun 	int ret;
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun 	if (!src_file.file)
235*4882a593Smuzhiyun 		return -EBADF;
236*4882a593Smuzhiyun 	ret = -EXDEV;
237*4882a593Smuzhiyun 	if (src_file.file->f_path.mnt != dst_file->f_path.mnt)
238*4882a593Smuzhiyun 		goto fdput;
239*4882a593Smuzhiyun 	cloned = vfs_clone_file_range(src_file.file, off, dst_file, destoff,
240*4882a593Smuzhiyun 				      olen, 0);
241*4882a593Smuzhiyun 	if (cloned < 0)
242*4882a593Smuzhiyun 		ret = cloned;
243*4882a593Smuzhiyun 	else if (olen && cloned != olen)
244*4882a593Smuzhiyun 		ret = -EINVAL;
245*4882a593Smuzhiyun 	else
246*4882a593Smuzhiyun 		ret = 0;
247*4882a593Smuzhiyun fdput:
248*4882a593Smuzhiyun 	fdput(src_file);
249*4882a593Smuzhiyun 	return ret;
250*4882a593Smuzhiyun }
251*4882a593Smuzhiyun 
ioctl_file_clone_range(struct file * file,struct file_clone_range __user * argp)252*4882a593Smuzhiyun static long ioctl_file_clone_range(struct file *file,
253*4882a593Smuzhiyun 				   struct file_clone_range __user *argp)
254*4882a593Smuzhiyun {
255*4882a593Smuzhiyun 	struct file_clone_range args;
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun 	if (copy_from_user(&args, argp, sizeof(args)))
258*4882a593Smuzhiyun 		return -EFAULT;
259*4882a593Smuzhiyun 	return ioctl_file_clone(file, args.src_fd, args.src_offset,
260*4882a593Smuzhiyun 				args.src_length, args.dest_offset);
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun #ifdef CONFIG_BLOCK
264*4882a593Smuzhiyun 
logical_to_blk(struct inode * inode,loff_t offset)265*4882a593Smuzhiyun static inline sector_t logical_to_blk(struct inode *inode, loff_t offset)
266*4882a593Smuzhiyun {
267*4882a593Smuzhiyun 	return (offset >> inode->i_blkbits);
268*4882a593Smuzhiyun }
269*4882a593Smuzhiyun 
blk_to_logical(struct inode * inode,sector_t blk)270*4882a593Smuzhiyun static inline loff_t blk_to_logical(struct inode *inode, sector_t blk)
271*4882a593Smuzhiyun {
272*4882a593Smuzhiyun 	return (blk << inode->i_blkbits);
273*4882a593Smuzhiyun }
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun /**
276*4882a593Smuzhiyun  * __generic_block_fiemap - FIEMAP for block based inodes (no locking)
277*4882a593Smuzhiyun  * @inode: the inode to map
278*4882a593Smuzhiyun  * @fieinfo: the fiemap info struct that will be passed back to userspace
279*4882a593Smuzhiyun  * @start: where to start mapping in the inode
280*4882a593Smuzhiyun  * @len: how much space to map
281*4882a593Smuzhiyun  * @get_block: the fs's get_block function
282*4882a593Smuzhiyun  *
283*4882a593Smuzhiyun  * This does FIEMAP for block based inodes.  Basically it will just loop
284*4882a593Smuzhiyun  * through get_block until we hit the number of extents we want to map, or we
285*4882a593Smuzhiyun  * go past the end of the file and hit a hole.
286*4882a593Smuzhiyun  *
287*4882a593Smuzhiyun  * If it is possible to have data blocks beyond a hole past @inode->i_size, then
288*4882a593Smuzhiyun  * please do not use this function, it will stop at the first unmapped block
289*4882a593Smuzhiyun  * beyond i_size.
290*4882a593Smuzhiyun  *
291*4882a593Smuzhiyun  * If you use this function directly, you need to do your own locking. Use
292*4882a593Smuzhiyun  * generic_block_fiemap if you want the locking done for you.
293*4882a593Smuzhiyun  */
__generic_block_fiemap(struct inode * inode,struct fiemap_extent_info * fieinfo,loff_t start,loff_t len,get_block_t * get_block)294*4882a593Smuzhiyun static int __generic_block_fiemap(struct inode *inode,
295*4882a593Smuzhiyun 			   struct fiemap_extent_info *fieinfo, loff_t start,
296*4882a593Smuzhiyun 			   loff_t len, get_block_t *get_block)
297*4882a593Smuzhiyun {
298*4882a593Smuzhiyun 	struct buffer_head map_bh;
299*4882a593Smuzhiyun 	sector_t start_blk, last_blk;
300*4882a593Smuzhiyun 	loff_t isize = i_size_read(inode);
301*4882a593Smuzhiyun 	u64 logical = 0, phys = 0, size = 0;
302*4882a593Smuzhiyun 	u32 flags = FIEMAP_EXTENT_MERGED;
303*4882a593Smuzhiyun 	bool past_eof = false, whole_file = false;
304*4882a593Smuzhiyun 	int ret = 0;
305*4882a593Smuzhiyun 
306*4882a593Smuzhiyun 	ret = fiemap_prep(inode, fieinfo, start, &len, FIEMAP_FLAG_SYNC);
307*4882a593Smuzhiyun 	if (ret)
308*4882a593Smuzhiyun 		return ret;
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun 	/*
311*4882a593Smuzhiyun 	 * Either the i_mutex or other appropriate locking needs to be held
312*4882a593Smuzhiyun 	 * since we expect isize to not change at all through the duration of
313*4882a593Smuzhiyun 	 * this call.
314*4882a593Smuzhiyun 	 */
315*4882a593Smuzhiyun 	if (len >= isize) {
316*4882a593Smuzhiyun 		whole_file = true;
317*4882a593Smuzhiyun 		len = isize;
318*4882a593Smuzhiyun 	}
319*4882a593Smuzhiyun 
320*4882a593Smuzhiyun 	/*
321*4882a593Smuzhiyun 	 * Some filesystems can't deal with being asked to map less than
322*4882a593Smuzhiyun 	 * blocksize, so make sure our len is at least block length.
323*4882a593Smuzhiyun 	 */
324*4882a593Smuzhiyun 	if (logical_to_blk(inode, len) == 0)
325*4882a593Smuzhiyun 		len = blk_to_logical(inode, 1);
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun 	start_blk = logical_to_blk(inode, start);
328*4882a593Smuzhiyun 	last_blk = logical_to_blk(inode, start + len - 1);
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun 	do {
331*4882a593Smuzhiyun 		/*
332*4882a593Smuzhiyun 		 * we set b_size to the total size we want so it will map as
333*4882a593Smuzhiyun 		 * many contiguous blocks as possible at once
334*4882a593Smuzhiyun 		 */
335*4882a593Smuzhiyun 		memset(&map_bh, 0, sizeof(struct buffer_head));
336*4882a593Smuzhiyun 		map_bh.b_size = len;
337*4882a593Smuzhiyun 
338*4882a593Smuzhiyun 		ret = get_block(inode, start_blk, &map_bh, 0);
339*4882a593Smuzhiyun 		if (ret)
340*4882a593Smuzhiyun 			break;
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun 		/* HOLE */
343*4882a593Smuzhiyun 		if (!buffer_mapped(&map_bh)) {
344*4882a593Smuzhiyun 			start_blk++;
345*4882a593Smuzhiyun 
346*4882a593Smuzhiyun 			/*
347*4882a593Smuzhiyun 			 * We want to handle the case where there is an
348*4882a593Smuzhiyun 			 * allocated block at the front of the file, and then
349*4882a593Smuzhiyun 			 * nothing but holes up to the end of the file properly,
350*4882a593Smuzhiyun 			 * to make sure that extent at the front gets properly
351*4882a593Smuzhiyun 			 * marked with FIEMAP_EXTENT_LAST
352*4882a593Smuzhiyun 			 */
353*4882a593Smuzhiyun 			if (!past_eof &&
354*4882a593Smuzhiyun 			    blk_to_logical(inode, start_blk) >= isize)
355*4882a593Smuzhiyun 				past_eof = 1;
356*4882a593Smuzhiyun 
357*4882a593Smuzhiyun 			/*
358*4882a593Smuzhiyun 			 * First hole after going past the EOF, this is our
359*4882a593Smuzhiyun 			 * last extent
360*4882a593Smuzhiyun 			 */
361*4882a593Smuzhiyun 			if (past_eof && size) {
362*4882a593Smuzhiyun 				flags = FIEMAP_EXTENT_MERGED|FIEMAP_EXTENT_LAST;
363*4882a593Smuzhiyun 				ret = fiemap_fill_next_extent(fieinfo, logical,
364*4882a593Smuzhiyun 							      phys, size,
365*4882a593Smuzhiyun 							      flags);
366*4882a593Smuzhiyun 			} else if (size) {
367*4882a593Smuzhiyun 				ret = fiemap_fill_next_extent(fieinfo, logical,
368*4882a593Smuzhiyun 							      phys, size, flags);
369*4882a593Smuzhiyun 				size = 0;
370*4882a593Smuzhiyun 			}
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun 			/* if we have holes up to/past EOF then we're done */
373*4882a593Smuzhiyun 			if (start_blk > last_blk || past_eof || ret)
374*4882a593Smuzhiyun 				break;
375*4882a593Smuzhiyun 		} else {
376*4882a593Smuzhiyun 			/*
377*4882a593Smuzhiyun 			 * We have gone over the length of what we wanted to
378*4882a593Smuzhiyun 			 * map, and it wasn't the entire file, so add the extent
379*4882a593Smuzhiyun 			 * we got last time and exit.
380*4882a593Smuzhiyun 			 *
381*4882a593Smuzhiyun 			 * This is for the case where say we want to map all the
382*4882a593Smuzhiyun 			 * way up to the second to the last block in a file, but
383*4882a593Smuzhiyun 			 * the last block is a hole, making the second to last
384*4882a593Smuzhiyun 			 * block FIEMAP_EXTENT_LAST.  In this case we want to
385*4882a593Smuzhiyun 			 * see if there is a hole after the second to last block
386*4882a593Smuzhiyun 			 * so we can mark it properly.  If we found data after
387*4882a593Smuzhiyun 			 * we exceeded the length we were requesting, then we
388*4882a593Smuzhiyun 			 * are good to go, just add the extent to the fieinfo
389*4882a593Smuzhiyun 			 * and break
390*4882a593Smuzhiyun 			 */
391*4882a593Smuzhiyun 			if (start_blk > last_blk && !whole_file) {
392*4882a593Smuzhiyun 				ret = fiemap_fill_next_extent(fieinfo, logical,
393*4882a593Smuzhiyun 							      phys, size,
394*4882a593Smuzhiyun 							      flags);
395*4882a593Smuzhiyun 				break;
396*4882a593Smuzhiyun 			}
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun 			/*
399*4882a593Smuzhiyun 			 * if size != 0 then we know we already have an extent
400*4882a593Smuzhiyun 			 * to add, so add it.
401*4882a593Smuzhiyun 			 */
402*4882a593Smuzhiyun 			if (size) {
403*4882a593Smuzhiyun 				ret = fiemap_fill_next_extent(fieinfo, logical,
404*4882a593Smuzhiyun 							      phys, size,
405*4882a593Smuzhiyun 							      flags);
406*4882a593Smuzhiyun 				if (ret)
407*4882a593Smuzhiyun 					break;
408*4882a593Smuzhiyun 			}
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun 			logical = blk_to_logical(inode, start_blk);
411*4882a593Smuzhiyun 			phys = blk_to_logical(inode, map_bh.b_blocknr);
412*4882a593Smuzhiyun 			size = map_bh.b_size;
413*4882a593Smuzhiyun 			flags = FIEMAP_EXTENT_MERGED;
414*4882a593Smuzhiyun 
415*4882a593Smuzhiyun 			start_blk += logical_to_blk(inode, size);
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun 			/*
418*4882a593Smuzhiyun 			 * If we are past the EOF, then we need to make sure as
419*4882a593Smuzhiyun 			 * soon as we find a hole that the last extent we found
420*4882a593Smuzhiyun 			 * is marked with FIEMAP_EXTENT_LAST
421*4882a593Smuzhiyun 			 */
422*4882a593Smuzhiyun 			if (!past_eof && logical + size >= isize)
423*4882a593Smuzhiyun 				past_eof = true;
424*4882a593Smuzhiyun 		}
425*4882a593Smuzhiyun 		cond_resched();
426*4882a593Smuzhiyun 		if (fatal_signal_pending(current)) {
427*4882a593Smuzhiyun 			ret = -EINTR;
428*4882a593Smuzhiyun 			break;
429*4882a593Smuzhiyun 		}
430*4882a593Smuzhiyun 
431*4882a593Smuzhiyun 	} while (1);
432*4882a593Smuzhiyun 
433*4882a593Smuzhiyun 	/* If ret is 1 then we just hit the end of the extent array */
434*4882a593Smuzhiyun 	if (ret == 1)
435*4882a593Smuzhiyun 		ret = 0;
436*4882a593Smuzhiyun 
437*4882a593Smuzhiyun 	return ret;
438*4882a593Smuzhiyun }
439*4882a593Smuzhiyun 
440*4882a593Smuzhiyun /**
441*4882a593Smuzhiyun  * generic_block_fiemap - FIEMAP for block based inodes
442*4882a593Smuzhiyun  * @inode: The inode to map
443*4882a593Smuzhiyun  * @fieinfo: The mapping information
444*4882a593Smuzhiyun  * @start: The initial block to map
445*4882a593Smuzhiyun  * @len: The length of the extect to attempt to map
446*4882a593Smuzhiyun  * @get_block: The block mapping function for the fs
447*4882a593Smuzhiyun  *
448*4882a593Smuzhiyun  * Calls __generic_block_fiemap to map the inode, after taking
449*4882a593Smuzhiyun  * the inode's mutex lock.
450*4882a593Smuzhiyun  */
451*4882a593Smuzhiyun 
generic_block_fiemap(struct inode * inode,struct fiemap_extent_info * fieinfo,u64 start,u64 len,get_block_t * get_block)452*4882a593Smuzhiyun int generic_block_fiemap(struct inode *inode,
453*4882a593Smuzhiyun 			 struct fiemap_extent_info *fieinfo, u64 start,
454*4882a593Smuzhiyun 			 u64 len, get_block_t *get_block)
455*4882a593Smuzhiyun {
456*4882a593Smuzhiyun 	int ret;
457*4882a593Smuzhiyun 	inode_lock(inode);
458*4882a593Smuzhiyun 	ret = __generic_block_fiemap(inode, fieinfo, start, len, get_block);
459*4882a593Smuzhiyun 	inode_unlock(inode);
460*4882a593Smuzhiyun 	return ret;
461*4882a593Smuzhiyun }
462*4882a593Smuzhiyun EXPORT_SYMBOL(generic_block_fiemap);
463*4882a593Smuzhiyun 
464*4882a593Smuzhiyun #endif  /*  CONFIG_BLOCK  */
465*4882a593Smuzhiyun 
466*4882a593Smuzhiyun /*
467*4882a593Smuzhiyun  * This provides compatibility with legacy XFS pre-allocation ioctls
468*4882a593Smuzhiyun  * which predate the fallocate syscall.
469*4882a593Smuzhiyun  *
470*4882a593Smuzhiyun  * Only the l_start, l_len and l_whence fields of the 'struct space_resv'
471*4882a593Smuzhiyun  * are used here, rest are ignored.
472*4882a593Smuzhiyun  */
ioctl_preallocate(struct file * filp,int mode,void __user * argp)473*4882a593Smuzhiyun static int ioctl_preallocate(struct file *filp, int mode, void __user *argp)
474*4882a593Smuzhiyun {
475*4882a593Smuzhiyun 	struct inode *inode = file_inode(filp);
476*4882a593Smuzhiyun 	struct space_resv sr;
477*4882a593Smuzhiyun 
478*4882a593Smuzhiyun 	if (copy_from_user(&sr, argp, sizeof(sr)))
479*4882a593Smuzhiyun 		return -EFAULT;
480*4882a593Smuzhiyun 
481*4882a593Smuzhiyun 	switch (sr.l_whence) {
482*4882a593Smuzhiyun 	case SEEK_SET:
483*4882a593Smuzhiyun 		break;
484*4882a593Smuzhiyun 	case SEEK_CUR:
485*4882a593Smuzhiyun 		sr.l_start += filp->f_pos;
486*4882a593Smuzhiyun 		break;
487*4882a593Smuzhiyun 	case SEEK_END:
488*4882a593Smuzhiyun 		sr.l_start += i_size_read(inode);
489*4882a593Smuzhiyun 		break;
490*4882a593Smuzhiyun 	default:
491*4882a593Smuzhiyun 		return -EINVAL;
492*4882a593Smuzhiyun 	}
493*4882a593Smuzhiyun 
494*4882a593Smuzhiyun 	return vfs_fallocate(filp, mode | FALLOC_FL_KEEP_SIZE, sr.l_start,
495*4882a593Smuzhiyun 			sr.l_len);
496*4882a593Smuzhiyun }
497*4882a593Smuzhiyun 
498*4882a593Smuzhiyun /* on ia32 l_start is on a 32-bit boundary */
499*4882a593Smuzhiyun #if defined CONFIG_COMPAT && defined(CONFIG_X86_64)
500*4882a593Smuzhiyun /* just account for different alignment */
compat_ioctl_preallocate(struct file * file,int mode,struct space_resv_32 __user * argp)501*4882a593Smuzhiyun static int compat_ioctl_preallocate(struct file *file, int mode,
502*4882a593Smuzhiyun 				    struct space_resv_32 __user *argp)
503*4882a593Smuzhiyun {
504*4882a593Smuzhiyun 	struct inode *inode = file_inode(file);
505*4882a593Smuzhiyun 	struct space_resv_32 sr;
506*4882a593Smuzhiyun 
507*4882a593Smuzhiyun 	if (copy_from_user(&sr, argp, sizeof(sr)))
508*4882a593Smuzhiyun 		return -EFAULT;
509*4882a593Smuzhiyun 
510*4882a593Smuzhiyun 	switch (sr.l_whence) {
511*4882a593Smuzhiyun 	case SEEK_SET:
512*4882a593Smuzhiyun 		break;
513*4882a593Smuzhiyun 	case SEEK_CUR:
514*4882a593Smuzhiyun 		sr.l_start += file->f_pos;
515*4882a593Smuzhiyun 		break;
516*4882a593Smuzhiyun 	case SEEK_END:
517*4882a593Smuzhiyun 		sr.l_start += i_size_read(inode);
518*4882a593Smuzhiyun 		break;
519*4882a593Smuzhiyun 	default:
520*4882a593Smuzhiyun 		return -EINVAL;
521*4882a593Smuzhiyun 	}
522*4882a593Smuzhiyun 
523*4882a593Smuzhiyun 	return vfs_fallocate(file, mode | FALLOC_FL_KEEP_SIZE, sr.l_start, sr.l_len);
524*4882a593Smuzhiyun }
525*4882a593Smuzhiyun #endif
526*4882a593Smuzhiyun 
file_ioctl(struct file * filp,unsigned int cmd,int __user * p)527*4882a593Smuzhiyun static int file_ioctl(struct file *filp, unsigned int cmd, int __user *p)
528*4882a593Smuzhiyun {
529*4882a593Smuzhiyun 	switch (cmd) {
530*4882a593Smuzhiyun 	case FIBMAP:
531*4882a593Smuzhiyun 		return ioctl_fibmap(filp, p);
532*4882a593Smuzhiyun 	case FS_IOC_RESVSP:
533*4882a593Smuzhiyun 	case FS_IOC_RESVSP64:
534*4882a593Smuzhiyun 		return ioctl_preallocate(filp, 0, p);
535*4882a593Smuzhiyun 	case FS_IOC_UNRESVSP:
536*4882a593Smuzhiyun 	case FS_IOC_UNRESVSP64:
537*4882a593Smuzhiyun 		return ioctl_preallocate(filp, FALLOC_FL_PUNCH_HOLE, p);
538*4882a593Smuzhiyun 	case FS_IOC_ZERO_RANGE:
539*4882a593Smuzhiyun 		return ioctl_preallocate(filp, FALLOC_FL_ZERO_RANGE, p);
540*4882a593Smuzhiyun 	}
541*4882a593Smuzhiyun 
542*4882a593Smuzhiyun 	return -ENOIOCTLCMD;
543*4882a593Smuzhiyun }
544*4882a593Smuzhiyun 
ioctl_fionbio(struct file * filp,int __user * argp)545*4882a593Smuzhiyun static int ioctl_fionbio(struct file *filp, int __user *argp)
546*4882a593Smuzhiyun {
547*4882a593Smuzhiyun 	unsigned int flag;
548*4882a593Smuzhiyun 	int on, error;
549*4882a593Smuzhiyun 
550*4882a593Smuzhiyun 	error = get_user(on, argp);
551*4882a593Smuzhiyun 	if (error)
552*4882a593Smuzhiyun 		return error;
553*4882a593Smuzhiyun 	flag = O_NONBLOCK;
554*4882a593Smuzhiyun #ifdef __sparc__
555*4882a593Smuzhiyun 	/* SunOS compatibility item. */
556*4882a593Smuzhiyun 	if (O_NONBLOCK != O_NDELAY)
557*4882a593Smuzhiyun 		flag |= O_NDELAY;
558*4882a593Smuzhiyun #endif
559*4882a593Smuzhiyun 	spin_lock(&filp->f_lock);
560*4882a593Smuzhiyun 	if (on)
561*4882a593Smuzhiyun 		filp->f_flags |= flag;
562*4882a593Smuzhiyun 	else
563*4882a593Smuzhiyun 		filp->f_flags &= ~flag;
564*4882a593Smuzhiyun 	spin_unlock(&filp->f_lock);
565*4882a593Smuzhiyun 	return error;
566*4882a593Smuzhiyun }
567*4882a593Smuzhiyun 
ioctl_fioasync(unsigned int fd,struct file * filp,int __user * argp)568*4882a593Smuzhiyun static int ioctl_fioasync(unsigned int fd, struct file *filp,
569*4882a593Smuzhiyun 			  int __user *argp)
570*4882a593Smuzhiyun {
571*4882a593Smuzhiyun 	unsigned int flag;
572*4882a593Smuzhiyun 	int on, error;
573*4882a593Smuzhiyun 
574*4882a593Smuzhiyun 	error = get_user(on, argp);
575*4882a593Smuzhiyun 	if (error)
576*4882a593Smuzhiyun 		return error;
577*4882a593Smuzhiyun 	flag = on ? FASYNC : 0;
578*4882a593Smuzhiyun 
579*4882a593Smuzhiyun 	/* Did FASYNC state change ? */
580*4882a593Smuzhiyun 	if ((flag ^ filp->f_flags) & FASYNC) {
581*4882a593Smuzhiyun 		if (filp->f_op->fasync)
582*4882a593Smuzhiyun 			/* fasync() adjusts filp->f_flags */
583*4882a593Smuzhiyun 			error = filp->f_op->fasync(fd, filp, on);
584*4882a593Smuzhiyun 		else
585*4882a593Smuzhiyun 			error = -ENOTTY;
586*4882a593Smuzhiyun 	}
587*4882a593Smuzhiyun 	return error < 0 ? error : 0;
588*4882a593Smuzhiyun }
589*4882a593Smuzhiyun 
ioctl_fsfreeze(struct file * filp)590*4882a593Smuzhiyun static int ioctl_fsfreeze(struct file *filp)
591*4882a593Smuzhiyun {
592*4882a593Smuzhiyun 	struct super_block *sb = file_inode(filp)->i_sb;
593*4882a593Smuzhiyun 
594*4882a593Smuzhiyun 	if (!ns_capable(sb->s_user_ns, CAP_SYS_ADMIN))
595*4882a593Smuzhiyun 		return -EPERM;
596*4882a593Smuzhiyun 
597*4882a593Smuzhiyun 	/* If filesystem doesn't support freeze feature, return. */
598*4882a593Smuzhiyun 	if (sb->s_op->freeze_fs == NULL && sb->s_op->freeze_super == NULL)
599*4882a593Smuzhiyun 		return -EOPNOTSUPP;
600*4882a593Smuzhiyun 
601*4882a593Smuzhiyun 	/* Freeze */
602*4882a593Smuzhiyun 	if (sb->s_op->freeze_super)
603*4882a593Smuzhiyun 		return sb->s_op->freeze_super(sb);
604*4882a593Smuzhiyun 	return freeze_super(sb);
605*4882a593Smuzhiyun }
606*4882a593Smuzhiyun 
ioctl_fsthaw(struct file * filp)607*4882a593Smuzhiyun static int ioctl_fsthaw(struct file *filp)
608*4882a593Smuzhiyun {
609*4882a593Smuzhiyun 	struct super_block *sb = file_inode(filp)->i_sb;
610*4882a593Smuzhiyun 
611*4882a593Smuzhiyun 	if (!ns_capable(sb->s_user_ns, CAP_SYS_ADMIN))
612*4882a593Smuzhiyun 		return -EPERM;
613*4882a593Smuzhiyun 
614*4882a593Smuzhiyun 	/* Thaw */
615*4882a593Smuzhiyun 	if (sb->s_op->thaw_super)
616*4882a593Smuzhiyun 		return sb->s_op->thaw_super(sb);
617*4882a593Smuzhiyun 	return thaw_super(sb);
618*4882a593Smuzhiyun }
619*4882a593Smuzhiyun 
ioctl_file_dedupe_range(struct file * file,struct file_dedupe_range __user * argp)620*4882a593Smuzhiyun static int ioctl_file_dedupe_range(struct file *file,
621*4882a593Smuzhiyun 				   struct file_dedupe_range __user *argp)
622*4882a593Smuzhiyun {
623*4882a593Smuzhiyun 	struct file_dedupe_range *same = NULL;
624*4882a593Smuzhiyun 	int ret;
625*4882a593Smuzhiyun 	unsigned long size;
626*4882a593Smuzhiyun 	u16 count;
627*4882a593Smuzhiyun 
628*4882a593Smuzhiyun 	if (get_user(count, &argp->dest_count)) {
629*4882a593Smuzhiyun 		ret = -EFAULT;
630*4882a593Smuzhiyun 		goto out;
631*4882a593Smuzhiyun 	}
632*4882a593Smuzhiyun 
633*4882a593Smuzhiyun 	size = offsetof(struct file_dedupe_range __user, info[count]);
634*4882a593Smuzhiyun 	if (size > PAGE_SIZE) {
635*4882a593Smuzhiyun 		ret = -ENOMEM;
636*4882a593Smuzhiyun 		goto out;
637*4882a593Smuzhiyun 	}
638*4882a593Smuzhiyun 
639*4882a593Smuzhiyun 	same = memdup_user(argp, size);
640*4882a593Smuzhiyun 	if (IS_ERR(same)) {
641*4882a593Smuzhiyun 		ret = PTR_ERR(same);
642*4882a593Smuzhiyun 		same = NULL;
643*4882a593Smuzhiyun 		goto out;
644*4882a593Smuzhiyun 	}
645*4882a593Smuzhiyun 
646*4882a593Smuzhiyun 	same->dest_count = count;
647*4882a593Smuzhiyun 	ret = vfs_dedupe_file_range(file, same);
648*4882a593Smuzhiyun 	if (ret)
649*4882a593Smuzhiyun 		goto out;
650*4882a593Smuzhiyun 
651*4882a593Smuzhiyun 	ret = copy_to_user(argp, same, size);
652*4882a593Smuzhiyun 	if (ret)
653*4882a593Smuzhiyun 		ret = -EFAULT;
654*4882a593Smuzhiyun 
655*4882a593Smuzhiyun out:
656*4882a593Smuzhiyun 	kfree(same);
657*4882a593Smuzhiyun 	return ret;
658*4882a593Smuzhiyun }
659*4882a593Smuzhiyun 
660*4882a593Smuzhiyun /*
661*4882a593Smuzhiyun  * do_vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d.
662*4882a593Smuzhiyun  * It's just a simple helper for sys_ioctl and compat_sys_ioctl.
663*4882a593Smuzhiyun  *
664*4882a593Smuzhiyun  * When you add any new common ioctls to the switches above and below,
665*4882a593Smuzhiyun  * please ensure they have compatible arguments in compat mode.
666*4882a593Smuzhiyun  */
do_vfs_ioctl(struct file * filp,unsigned int fd,unsigned int cmd,unsigned long arg)667*4882a593Smuzhiyun static int do_vfs_ioctl(struct file *filp, unsigned int fd,
668*4882a593Smuzhiyun 			unsigned int cmd, unsigned long arg)
669*4882a593Smuzhiyun {
670*4882a593Smuzhiyun 	void __user *argp = (void __user *)arg;
671*4882a593Smuzhiyun 	struct inode *inode = file_inode(filp);
672*4882a593Smuzhiyun 
673*4882a593Smuzhiyun 	switch (cmd) {
674*4882a593Smuzhiyun 	case FIOCLEX:
675*4882a593Smuzhiyun 		set_close_on_exec(fd, 1);
676*4882a593Smuzhiyun 		return 0;
677*4882a593Smuzhiyun 
678*4882a593Smuzhiyun 	case FIONCLEX:
679*4882a593Smuzhiyun 		set_close_on_exec(fd, 0);
680*4882a593Smuzhiyun 		return 0;
681*4882a593Smuzhiyun 
682*4882a593Smuzhiyun 	case FIONBIO:
683*4882a593Smuzhiyun 		return ioctl_fionbio(filp, argp);
684*4882a593Smuzhiyun 
685*4882a593Smuzhiyun 	case FIOASYNC:
686*4882a593Smuzhiyun 		return ioctl_fioasync(fd, filp, argp);
687*4882a593Smuzhiyun 
688*4882a593Smuzhiyun 	case FIOQSIZE:
689*4882a593Smuzhiyun 		if (S_ISDIR(inode->i_mode) || S_ISREG(inode->i_mode) ||
690*4882a593Smuzhiyun 		    S_ISLNK(inode->i_mode)) {
691*4882a593Smuzhiyun 			loff_t res = inode_get_bytes(inode);
692*4882a593Smuzhiyun 			return copy_to_user(argp, &res, sizeof(res)) ?
693*4882a593Smuzhiyun 					    -EFAULT : 0;
694*4882a593Smuzhiyun 		}
695*4882a593Smuzhiyun 
696*4882a593Smuzhiyun 		return -ENOTTY;
697*4882a593Smuzhiyun 
698*4882a593Smuzhiyun 	case FIFREEZE:
699*4882a593Smuzhiyun 		return ioctl_fsfreeze(filp);
700*4882a593Smuzhiyun 
701*4882a593Smuzhiyun 	case FITHAW:
702*4882a593Smuzhiyun 		return ioctl_fsthaw(filp);
703*4882a593Smuzhiyun 
704*4882a593Smuzhiyun 	case FS_IOC_FIEMAP:
705*4882a593Smuzhiyun 		return ioctl_fiemap(filp, argp);
706*4882a593Smuzhiyun 
707*4882a593Smuzhiyun 	case FIGETBSZ:
708*4882a593Smuzhiyun 		/* anon_bdev filesystems may not have a block size */
709*4882a593Smuzhiyun 		if (!inode->i_sb->s_blocksize)
710*4882a593Smuzhiyun 			return -EINVAL;
711*4882a593Smuzhiyun 
712*4882a593Smuzhiyun 		return put_user(inode->i_sb->s_blocksize, (int __user *)argp);
713*4882a593Smuzhiyun 
714*4882a593Smuzhiyun 	case FICLONE:
715*4882a593Smuzhiyun 		return ioctl_file_clone(filp, arg, 0, 0, 0);
716*4882a593Smuzhiyun 
717*4882a593Smuzhiyun 	case FICLONERANGE:
718*4882a593Smuzhiyun 		return ioctl_file_clone_range(filp, argp);
719*4882a593Smuzhiyun 
720*4882a593Smuzhiyun 	case FIDEDUPERANGE:
721*4882a593Smuzhiyun 		return ioctl_file_dedupe_range(filp, argp);
722*4882a593Smuzhiyun 
723*4882a593Smuzhiyun 	case FIONREAD:
724*4882a593Smuzhiyun 		if (!S_ISREG(inode->i_mode))
725*4882a593Smuzhiyun 			return vfs_ioctl(filp, cmd, arg);
726*4882a593Smuzhiyun 
727*4882a593Smuzhiyun 		return put_user(i_size_read(inode) - filp->f_pos,
728*4882a593Smuzhiyun 				(int __user *)argp);
729*4882a593Smuzhiyun 
730*4882a593Smuzhiyun 	default:
731*4882a593Smuzhiyun 		if (S_ISREG(inode->i_mode))
732*4882a593Smuzhiyun 			return file_ioctl(filp, cmd, argp);
733*4882a593Smuzhiyun 		break;
734*4882a593Smuzhiyun 	}
735*4882a593Smuzhiyun 
736*4882a593Smuzhiyun 	return -ENOIOCTLCMD;
737*4882a593Smuzhiyun }
738*4882a593Smuzhiyun 
SYSCALL_DEFINE3(ioctl,unsigned int,fd,unsigned int,cmd,unsigned long,arg)739*4882a593Smuzhiyun SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, unsigned long, arg)
740*4882a593Smuzhiyun {
741*4882a593Smuzhiyun 	struct fd f = fdget(fd);
742*4882a593Smuzhiyun 	int error;
743*4882a593Smuzhiyun 
744*4882a593Smuzhiyun 	if (!f.file)
745*4882a593Smuzhiyun 		return -EBADF;
746*4882a593Smuzhiyun 
747*4882a593Smuzhiyun 	error = security_file_ioctl(f.file, cmd, arg);
748*4882a593Smuzhiyun 	if (error)
749*4882a593Smuzhiyun 		goto out;
750*4882a593Smuzhiyun 
751*4882a593Smuzhiyun 	error = do_vfs_ioctl(f.file, fd, cmd, arg);
752*4882a593Smuzhiyun 	if (error == -ENOIOCTLCMD)
753*4882a593Smuzhiyun 		error = vfs_ioctl(f.file, cmd, arg);
754*4882a593Smuzhiyun 
755*4882a593Smuzhiyun out:
756*4882a593Smuzhiyun 	fdput(f);
757*4882a593Smuzhiyun 	return error;
758*4882a593Smuzhiyun }
759*4882a593Smuzhiyun 
760*4882a593Smuzhiyun #ifdef CONFIG_COMPAT
761*4882a593Smuzhiyun /**
762*4882a593Smuzhiyun  * compat_ptr_ioctl - generic implementation of .compat_ioctl file operation
763*4882a593Smuzhiyun  *
764*4882a593Smuzhiyun  * This is not normally called as a function, but instead set in struct
765*4882a593Smuzhiyun  * file_operations as
766*4882a593Smuzhiyun  *
767*4882a593Smuzhiyun  *     .compat_ioctl = compat_ptr_ioctl,
768*4882a593Smuzhiyun  *
769*4882a593Smuzhiyun  * On most architectures, the compat_ptr_ioctl() just passes all arguments
770*4882a593Smuzhiyun  * to the corresponding ->ioctl handler. The exception is arch/s390, where
771*4882a593Smuzhiyun  * compat_ptr() clears the top bit of a 32-bit pointer value, so user space
772*4882a593Smuzhiyun  * pointers to the second 2GB alias the first 2GB, as is the case for
773*4882a593Smuzhiyun  * native 32-bit s390 user space.
774*4882a593Smuzhiyun  *
775*4882a593Smuzhiyun  * The compat_ptr_ioctl() function must therefore be used only with ioctl
776*4882a593Smuzhiyun  * functions that either ignore the argument or pass a pointer to a
777*4882a593Smuzhiyun  * compatible data type.
778*4882a593Smuzhiyun  *
779*4882a593Smuzhiyun  * If any ioctl command handled by fops->unlocked_ioctl passes a plain
780*4882a593Smuzhiyun  * integer instead of a pointer, or any of the passed data types
781*4882a593Smuzhiyun  * is incompatible between 32-bit and 64-bit architectures, a proper
782*4882a593Smuzhiyun  * handler is required instead of compat_ptr_ioctl.
783*4882a593Smuzhiyun  */
compat_ptr_ioctl(struct file * file,unsigned int cmd,unsigned long arg)784*4882a593Smuzhiyun long compat_ptr_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
785*4882a593Smuzhiyun {
786*4882a593Smuzhiyun 	if (!file->f_op->unlocked_ioctl)
787*4882a593Smuzhiyun 		return -ENOIOCTLCMD;
788*4882a593Smuzhiyun 
789*4882a593Smuzhiyun 	return file->f_op->unlocked_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
790*4882a593Smuzhiyun }
791*4882a593Smuzhiyun EXPORT_SYMBOL(compat_ptr_ioctl);
792*4882a593Smuzhiyun 
COMPAT_SYSCALL_DEFINE3(ioctl,unsigned int,fd,unsigned int,cmd,compat_ulong_t,arg)793*4882a593Smuzhiyun COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd,
794*4882a593Smuzhiyun 		       compat_ulong_t, arg)
795*4882a593Smuzhiyun {
796*4882a593Smuzhiyun 	struct fd f = fdget(fd);
797*4882a593Smuzhiyun 	int error;
798*4882a593Smuzhiyun 
799*4882a593Smuzhiyun 	if (!f.file)
800*4882a593Smuzhiyun 		return -EBADF;
801*4882a593Smuzhiyun 
802*4882a593Smuzhiyun 	/* RED-PEN how should LSM module know it's handling 32bit? */
803*4882a593Smuzhiyun 	error = security_file_ioctl(f.file, cmd, arg);
804*4882a593Smuzhiyun 	if (error)
805*4882a593Smuzhiyun 		goto out;
806*4882a593Smuzhiyun 
807*4882a593Smuzhiyun 	switch (cmd) {
808*4882a593Smuzhiyun 	/* FICLONE takes an int argument, so don't use compat_ptr() */
809*4882a593Smuzhiyun 	case FICLONE:
810*4882a593Smuzhiyun 		error = ioctl_file_clone(f.file, arg, 0, 0, 0);
811*4882a593Smuzhiyun 		break;
812*4882a593Smuzhiyun 
813*4882a593Smuzhiyun #if defined(CONFIG_X86_64)
814*4882a593Smuzhiyun 	/* these get messy on amd64 due to alignment differences */
815*4882a593Smuzhiyun 	case FS_IOC_RESVSP_32:
816*4882a593Smuzhiyun 	case FS_IOC_RESVSP64_32:
817*4882a593Smuzhiyun 		error = compat_ioctl_preallocate(f.file, 0, compat_ptr(arg));
818*4882a593Smuzhiyun 		break;
819*4882a593Smuzhiyun 	case FS_IOC_UNRESVSP_32:
820*4882a593Smuzhiyun 	case FS_IOC_UNRESVSP64_32:
821*4882a593Smuzhiyun 		error = compat_ioctl_preallocate(f.file, FALLOC_FL_PUNCH_HOLE,
822*4882a593Smuzhiyun 				compat_ptr(arg));
823*4882a593Smuzhiyun 		break;
824*4882a593Smuzhiyun 	case FS_IOC_ZERO_RANGE_32:
825*4882a593Smuzhiyun 		error = compat_ioctl_preallocate(f.file, FALLOC_FL_ZERO_RANGE,
826*4882a593Smuzhiyun 				compat_ptr(arg));
827*4882a593Smuzhiyun 		break;
828*4882a593Smuzhiyun #endif
829*4882a593Smuzhiyun 
830*4882a593Smuzhiyun 	/*
831*4882a593Smuzhiyun 	 * everything else in do_vfs_ioctl() takes either a compatible
832*4882a593Smuzhiyun 	 * pointer argument or no argument -- call it with a modified
833*4882a593Smuzhiyun 	 * argument.
834*4882a593Smuzhiyun 	 */
835*4882a593Smuzhiyun 	default:
836*4882a593Smuzhiyun 		error = do_vfs_ioctl(f.file, fd, cmd,
837*4882a593Smuzhiyun 				     (unsigned long)compat_ptr(arg));
838*4882a593Smuzhiyun 		if (error != -ENOIOCTLCMD)
839*4882a593Smuzhiyun 			break;
840*4882a593Smuzhiyun 
841*4882a593Smuzhiyun 		if (f.file->f_op->compat_ioctl)
842*4882a593Smuzhiyun 			error = f.file->f_op->compat_ioctl(f.file, cmd, arg);
843*4882a593Smuzhiyun 		if (error == -ENOIOCTLCMD)
844*4882a593Smuzhiyun 			error = -ENOTTY;
845*4882a593Smuzhiyun 		break;
846*4882a593Smuzhiyun 	}
847*4882a593Smuzhiyun 
848*4882a593Smuzhiyun  out:
849*4882a593Smuzhiyun 	fdput(f);
850*4882a593Smuzhiyun 
851*4882a593Smuzhiyun 	return error;
852*4882a593Smuzhiyun }
853*4882a593Smuzhiyun #endif
854