ioctl.c 17.7 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0
Linus Torvalds's avatar
Linus Torvalds committed
2 3 4 5 6 7 8 9
/*
 *  linux/fs/ioctl.c
 *
 *  Copyright (C) 1991, 1992  Linus Torvalds
 */

#include <linux/syscalls.h>
#include <linux/mm.h>
10
#include <linux/capability.h>
Linus Torvalds's avatar
Linus Torvalds committed
11 12 13
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/security.h>
14
#include <linux/export.h>
15
#include <linux/uaccess.h>
16 17
#include <linux/writeback.h>
#include <linux/buffer_head.h>
18
#include <linux/falloc.h>
19 20
#include <linux/sched/signal.h>

21
#include "internal.h"
Linus Torvalds's avatar
Linus Torvalds committed
22 23 24

#include <asm/ioctls.h>

25 26 27
/* So that the fiemap access checks can't overflow on 32 bit machines. */
#define FIEMAP_MAX_EXTENTS	(UINT_MAX / sizeof(struct fiemap_extent))

28 29
/**
 * vfs_ioctl - call filesystem specific ioctl methods
30 31 32
 * @filp:	open file to invoke ioctl method on
 * @cmd:	ioctl command to execute
 * @arg:	command-specific argument for ioctl
33 34 35 36 37 38
 *
 * Invokes filesystem specific ->unlocked_ioctl, if one exists; otherwise
 * returns -ENOTTY.
 *
 * Returns 0 on success, -errno on error.
 */
39
long vfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
Linus Torvalds's avatar
Linus Torvalds committed
40 41 42
{
	int error = -ENOTTY;

Al Viro's avatar
Al Viro committed
43
	if (!filp->f_op->unlocked_ioctl)
Linus Torvalds's avatar
Linus Torvalds committed
44 45
		goto out;

46 47
	error = filp->f_op->unlocked_ioctl(filp, cmd, arg);
	if (error == -ENOIOCTLCMD)
48
		error = -ENOTTY;
Linus Torvalds's avatar
Linus Torvalds committed
49 50 51
 out:
	return error;
}
52
EXPORT_SYMBOL(vfs_ioctl);
Linus Torvalds's avatar
Linus Torvalds committed
53

54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
static int ioctl_fibmap(struct file *filp, int __user *p)
{
	struct address_space *mapping = filp->f_mapping;
	int res, block;

	/* do we support this mess? */
	if (!mapping->a_ops->bmap)
		return -EINVAL;
	if (!capable(CAP_SYS_RAWIO))
		return -EPERM;
	res = get_user(block, p);
	if (res)
		return res;
	res = mapping->a_ops->bmap(mapping, block);
	return put_user(res, p);
}

71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
/**
 * fiemap_fill_next_extent - Fiemap helper function
 * @fieinfo:	Fiemap context passed into ->fiemap
 * @logical:	Extent logical start offset, in bytes
 * @phys:	Extent physical start offset, in bytes
 * @len:	Extent length, in bytes
 * @flags:	FIEMAP_EXTENT flags that describe this extent
 *
 * Called from file system ->fiemap callback. Will populate extent
 * info as passed in via arguments and copy to user memory. On
 * success, extent count on fieinfo is incremented.
 *
 * Returns 0 on success, -errno on error, 1 if this was the last
 * extent that will fit in user array.
 */
#define SET_UNKNOWN_FLAGS	(FIEMAP_EXTENT_DELALLOC)
#define SET_NO_UNMOUNTED_IO_FLAGS	(FIEMAP_EXTENT_DATA_ENCRYPTED)
#define SET_NOT_ALIGNED_FLAGS	(FIEMAP_EXTENT_DATA_TAIL|FIEMAP_EXTENT_DATA_INLINE)
int fiemap_fill_next_extent(struct fiemap_extent_info *fieinfo, u64 logical,
			    u64 phys, u64 len, u32 flags)
{
	struct fiemap_extent extent;
93
	struct fiemap_extent __user *dest = fieinfo->fi_extents_start;
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157

	/* only count the extents */
	if (fieinfo->fi_extents_max == 0) {
		fieinfo->fi_extents_mapped++;
		return (flags & FIEMAP_EXTENT_LAST) ? 1 : 0;
	}

	if (fieinfo->fi_extents_mapped >= fieinfo->fi_extents_max)
		return 1;

	if (flags & SET_UNKNOWN_FLAGS)
		flags |= FIEMAP_EXTENT_UNKNOWN;
	if (flags & SET_NO_UNMOUNTED_IO_FLAGS)
		flags |= FIEMAP_EXTENT_ENCODED;
	if (flags & SET_NOT_ALIGNED_FLAGS)
		flags |= FIEMAP_EXTENT_NOT_ALIGNED;

	memset(&extent, 0, sizeof(extent));
	extent.fe_logical = logical;
	extent.fe_physical = phys;
	extent.fe_length = len;
	extent.fe_flags = flags;

	dest += fieinfo->fi_extents_mapped;
	if (copy_to_user(dest, &extent, sizeof(extent)))
		return -EFAULT;

	fieinfo->fi_extents_mapped++;
	if (fieinfo->fi_extents_mapped == fieinfo->fi_extents_max)
		return 1;
	return (flags & FIEMAP_EXTENT_LAST) ? 1 : 0;
}
EXPORT_SYMBOL(fiemap_fill_next_extent);

/**
 * fiemap_check_flags - check validity of requested flags for fiemap
 * @fieinfo:	Fiemap context passed into ->fiemap
 * @fs_flags:	Set of fiemap flags that the file system understands
 *
 * Called from file system ->fiemap callback. This will compute the
 * intersection of valid fiemap flags and those that the fs supports. That
 * value is then compared against the user supplied flags. In case of bad user
 * flags, the invalid values will be written into the fieinfo structure, and
 * -EBADR is returned, which tells ioctl_fiemap() to return those values to
 * userspace. For this reason, a return code of -EBADR should be preserved.
 *
 * Returns 0 on success, -EBADR on bad flags.
 */
int fiemap_check_flags(struct fiemap_extent_info *fieinfo, u32 fs_flags)
{
	u32 incompat_flags;

	incompat_flags = fieinfo->fi_flags & ~(FIEMAP_FLAGS_COMPAT & fs_flags);
	if (incompat_flags) {
		fieinfo->fi_flags = incompat_flags;
		return -EBADR;
	}
	return 0;
}
EXPORT_SYMBOL(fiemap_check_flags);

static int fiemap_check_ranges(struct super_block *sb,
			       u64 start, u64 len, u64 *new_len)
{
158 159
	u64 maxbytes = (u64) sb->s_maxbytes;

160 161 162 163 164
	*new_len = len;

	if (len == 0)
		return -EINVAL;

165
	if (start > maxbytes)
166 167 168 169 170
		return -EFBIG;

	/*
	 * Shrink request scope to what the fs can actually handle.
	 */
171 172
	if (len > maxbytes || (maxbytes - len) < start)
		*new_len = maxbytes - start;
173 174 175 176 177 178 179

	return 0;
}

static int ioctl_fiemap(struct file *filp, unsigned long arg)
{
	struct fiemap fiemap;
180
	struct fiemap __user *ufiemap = (struct fiemap __user *) arg;
181
	struct fiemap_extent_info fieinfo = { 0, };
Al Viro's avatar
Al Viro committed
182
	struct inode *inode = file_inode(filp);
183 184 185 186 187 188 189
	struct super_block *sb = inode->i_sb;
	u64 len;
	int error;

	if (!inode->i_op->fiemap)
		return -EOPNOTSUPP;

190
	if (copy_from_user(&fiemap, ufiemap, sizeof(fiemap)))
191 192 193 194 195 196 197 198 199 200 201 202
		return -EFAULT;

	if (fiemap.fm_extent_count > FIEMAP_MAX_EXTENTS)
		return -EINVAL;

	error = fiemap_check_ranges(sb, fiemap.fm_start, fiemap.fm_length,
				    &len);
	if (error)
		return error;

	fieinfo.fi_flags = fiemap.fm_flags;
	fieinfo.fi_extents_max = fiemap.fm_extent_count;
203
	fieinfo.fi_extents_start = ufiemap->fm_extents;
204 205

	if (fiemap.fm_extent_count != 0 &&
206
	    !access_ok(fieinfo.fi_extents_start,
207 208 209 210 211 212 213 214 215
		       fieinfo.fi_extents_max * sizeof(struct fiemap_extent)))
		return -EFAULT;

	if (fieinfo.fi_flags & FIEMAP_FLAG_SYNC)
		filemap_write_and_wait(inode->i_mapping);

	error = inode->i_op->fiemap(inode, &fieinfo, fiemap.fm_start, len);
	fiemap.fm_flags = fieinfo.fi_flags;
	fiemap.fm_mapped_extents = fieinfo.fi_extents_mapped;
216
	if (copy_to_user(ufiemap, &fiemap, sizeof(fiemap)))
217 218 219 220 221
		error = -EFAULT;

	return error;
}

222 223 224 225
static long ioctl_file_clone(struct file *dst_file, unsigned long srcfd,
			     u64 off, u64 olen, u64 destoff)
{
	struct fd src_file = fdget(srcfd);
226
	loff_t cloned;
227 228 229 230
	int ret;

	if (!src_file.file)
		return -EBADF;
231 232 233
	ret = -EXDEV;
	if (src_file.file->f_path.mnt != dst_file->f_path.mnt)
		goto fdput;
234
	cloned = vfs_clone_file_range(src_file.file, off, dst_file, destoff,
235
				      olen, 0);
236 237 238 239 240 241
	if (cloned < 0)
		ret = cloned;
	else if (olen && cloned != olen)
		ret = -EINVAL;
	else
		ret = 0;
242
fdput:
243 244 245 246 247 248 249 250 251 252 253 254 255 256
	fdput(src_file);
	return ret;
}

static long ioctl_file_clone_range(struct file *file, void __user *argp)
{
	struct file_clone_range args;

	if (copy_from_user(&args, argp, sizeof(args)))
		return -EFAULT;
	return ioctl_file_clone(file, args.src_fd, args.src_offset,
				args.src_length, args.dest_offset);
}

257 258
#ifdef CONFIG_BLOCK

259 260 261 262 263 264 265 266 267
static inline sector_t logical_to_blk(struct inode *inode, loff_t offset)
{
	return (offset >> inode->i_blkbits);
}

static inline loff_t blk_to_logical(struct inode *inode, sector_t blk)
{
	return (blk << inode->i_blkbits);
}
268

269 270
/**
 * __generic_block_fiemap - FIEMAP for block based inodes (no locking)
271 272 273 274 275
 * @inode: the inode to map
 * @fieinfo: the fiemap info struct that will be passed back to userspace
 * @start: where to start mapping in the inode
 * @len: how much space to map
 * @get_block: the fs's get_block function
276 277 278 279 280 281 282
 *
 * This does FIEMAP for block based inodes.  Basically it will just loop
 * through get_block until we hit the number of extents we want to map, or we
 * go past the end of the file and hit a hole.
 *
 * If it is possible to have data blocks beyond a hole past @inode->i_size, then
 * please do not use this function, it will stop at the first unmapped block
283 284 285 286
 * beyond i_size.
 *
 * If you use this function directly, you need to do your own locking. Use
 * generic_block_fiemap if you want the locking done for you.
287
 */
288 289

int __generic_block_fiemap(struct inode *inode,
290 291
			   struct fiemap_extent_info *fieinfo, loff_t start,
			   loff_t len, get_block_t *get_block)
292
{
293 294 295
	struct buffer_head map_bh;
	sector_t start_blk, last_blk;
	loff_t isize = i_size_read(inode);
296 297
	u64 logical = 0, phys = 0, size = 0;
	u32 flags = FIEMAP_EXTENT_MERGED;
298 299
	bool past_eof = false, whole_file = false;
	int ret = 0;
300

301 302
	ret = fiemap_check_flags(fieinfo, FIEMAP_FLAG_SYNC);
	if (ret)
303 304
		return ret;

305 306 307 308 309 310 311 312 313
	/*
	 * Either the i_mutex or other appropriate locking needs to be held
	 * since we expect isize to not change at all through the duration of
	 * this call.
	 */
	if (len >= isize) {
		whole_file = true;
		len = isize;
	}
314

315 316 317 318 319 320 321
	/*
	 * Some filesystems can't deal with being asked to map less than
	 * blocksize, so make sure our len is at least block length.
	 */
	if (logical_to_blk(inode, len) == 0)
		len = blk_to_logical(inode, 1);

322 323
	start_blk = logical_to_blk(inode, start);
	last_blk = logical_to_blk(inode, start + len - 1);
324 325 326 327 328 329

	do {
		/*
		 * we set b_size to the total size we want so it will map as
		 * many contiguous blocks as possible at once
		 */
330 331
		memset(&map_bh, 0, sizeof(struct buffer_head));
		map_bh.b_size = len;
332

333
		ret = get_block(inode, start_blk, &map_bh, 0);
334 335 336 337
		if (ret)
			break;

		/* HOLE */
338
		if (!buffer_mapped(&map_bh)) {
339 340 341
			start_blk++;

			/*
342
			 * We want to handle the case where there is an
343 344 345 346 347 348
			 * allocated block at the front of the file, and then
			 * nothing but holes up to the end of the file properly,
			 * to make sure that extent at the front gets properly
			 * marked with FIEMAP_EXTENT_LAST
			 */
			if (!past_eof &&
349
			    blk_to_logical(inode, start_blk) >= isize)
350 351
				past_eof = 1;

352
			/*
353
			 * First hole after going past the EOF, this is our
354 355
			 * last extent
			 */
356
			if (past_eof && size) {
357 358 359 360
				flags = FIEMAP_EXTENT_MERGED|FIEMAP_EXTENT_LAST;
				ret = fiemap_fill_next_extent(fieinfo, logical,
							      phys, size,
							      flags);
361 362 363 364
			} else if (size) {
				ret = fiemap_fill_next_extent(fieinfo, logical,
							      phys, size, flags);
				size = 0;
365 366 367
			}

			/* if we have holes up to/past EOF then we're done */
368
			if (start_blk > last_blk || past_eof || ret)
369 370
				break;
		} else {
371
			/*
372
			 * We have gone over the length of what we wanted to
373 374 375 376 377 378 379 380 381 382 383 384 385
			 * map, and it wasn't the entire file, so add the extent
			 * we got last time and exit.
			 *
			 * This is for the case where say we want to map all the
			 * way up to the second to the last block in a file, but
			 * the last block is a hole, making the second to last
			 * block FIEMAP_EXTENT_LAST.  In this case we want to
			 * see if there is a hole after the second to last block
			 * so we can mark it properly.  If we found data after
			 * we exceeded the length we were requesting, then we
			 * are good to go, just add the extent to the fieinfo
			 * and break
			 */
386
			if (start_blk > last_blk && !whole_file) {
387 388 389 390 391 392 393 394 395 396 397
				ret = fiemap_fill_next_extent(fieinfo, logical,
							      phys, size,
							      flags);
				break;
			}

			/*
			 * if size != 0 then we know we already have an extent
			 * to add, so add it.
			 */
			if (size) {
398 399 400 401 402 403 404 405
				ret = fiemap_fill_next_extent(fieinfo, logical,
							      phys, size,
							      flags);
				if (ret)
					break;
			}

			logical = blk_to_logical(inode, start_blk);
406 407
			phys = blk_to_logical(inode, map_bh.b_blocknr);
			size = map_bh.b_size;
408 409 410 411 412
			flags = FIEMAP_EXTENT_MERGED;

			start_blk += logical_to_blk(inode, size);

			/*
413 414 415
			 * If we are past the EOF, then we need to make sure as
			 * soon as we find a hole that the last extent we found
			 * is marked with FIEMAP_EXTENT_LAST
416
			 */
417 418
			if (!past_eof && logical + size >= isize)
				past_eof = true;
419 420
		}
		cond_resched();
421 422 423 424 425
		if (fatal_signal_pending(current)) {
			ret = -EINTR;
			break;
		}

426 427
	} while (1);

428
	/* If ret is 1 then we just hit the end of the extent array */
429 430 431 432 433
	if (ret == 1)
		ret = 0;

	return ret;
}
434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452
EXPORT_SYMBOL(__generic_block_fiemap);

/**
 * generic_block_fiemap - FIEMAP for block based inodes
 * @inode: The inode to map
 * @fieinfo: The mapping information
 * @start: The initial block to map
 * @len: The length of the extect to attempt to map
 * @get_block: The block mapping function for the fs
 *
 * Calls __generic_block_fiemap to map the inode, after taking
 * the inode's mutex lock.
 */

int generic_block_fiemap(struct inode *inode,
			 struct fiemap_extent_info *fieinfo, u64 start,
			 u64 len, get_block_t *get_block)
{
	int ret;
Al Viro's avatar
Al Viro committed
453
	inode_lock(inode);
454
	ret = __generic_block_fiemap(inode, fieinfo, start, len, get_block);
Al Viro's avatar
Al Viro committed
455
	inode_unlock(inode);
456 457
	return ret;
}
458 459
EXPORT_SYMBOL(generic_block_fiemap);

460 461
#endif  /*  CONFIG_BLOCK  */

462 463 464 465 466 467 468 469 470
/*
 * This provides compatibility with legacy XFS pre-allocation ioctls
 * which predate the fallocate syscall.
 *
 * Only the l_start, l_len and l_whence fields of the 'struct space_resv'
 * are used here, rest are ignored.
 */
int ioctl_preallocate(struct file *filp, void __user *argp)
{
Al Viro's avatar
Al Viro committed
471
	struct inode *inode = file_inode(filp);
472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489
	struct space_resv sr;

	if (copy_from_user(&sr, argp, sizeof(sr)))
		return -EFAULT;

	switch (sr.l_whence) {
	case SEEK_SET:
		break;
	case SEEK_CUR:
		sr.l_start += filp->f_pos;
		break;
	case SEEK_END:
		sr.l_start += i_size_read(inode);
		break;
	default:
		return -EINVAL;
	}

490
	return vfs_fallocate(filp, FALLOC_FL_KEEP_SIZE, sr.l_start, sr.l_len);
491 492
}

Linus Torvalds's avatar
Linus Torvalds committed
493 494 495
static int file_ioctl(struct file *filp, unsigned int cmd,
		unsigned long arg)
{
Al Viro's avatar
Al Viro committed
496
	struct inode *inode = file_inode(filp);
Linus Torvalds's avatar
Linus Torvalds committed
497 498 499
	int __user *p = (int __user *)arg;

	switch (cmd) {
500
	case FIBMAP:
501
		return ioctl_fibmap(filp, p);
502 503
	case FIONREAD:
		return put_user(i_size_read(inode) - filp->f_pos, p);
504 505 506
	case FS_IOC_RESVSP:
	case FS_IOC_RESVSP64:
		return ioctl_preallocate(filp, p);
Linus Torvalds's avatar
Linus Torvalds committed
507 508
	}

509
	return vfs_ioctl(filp, cmd, arg);
Linus Torvalds's avatar
Linus Torvalds committed
510 511
}

512 513 514 515 516 517 518 519 520 521 522 523 524 525
static int ioctl_fionbio(struct file *filp, int __user *argp)
{
	unsigned int flag;
	int on, error;

	error = get_user(on, argp);
	if (error)
		return error;
	flag = O_NONBLOCK;
#ifdef __sparc__
	/* SunOS compatibility item. */
	if (O_NONBLOCK != O_NDELAY)
		flag |= O_NDELAY;
#endif
526
	spin_lock(&filp->f_lock);
527 528 529 530
	if (on)
		filp->f_flags |= flag;
	else
		filp->f_flags &= ~flag;
531
	spin_unlock(&filp->f_lock);
532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547
	return error;
}

static int ioctl_fioasync(unsigned int fd, struct file *filp,
			  int __user *argp)
{
	unsigned int flag;
	int on, error;

	error = get_user(on, argp);
	if (error)
		return error;
	flag = on ? FASYNC : 0;

	/* Did FASYNC state change ? */
	if ((flag ^ filp->f_flags) & FASYNC) {
Al Viro's avatar
Al Viro committed
548
		if (filp->f_op->fasync)
549
			/* fasync() adjusts filp->f_flags */
550
			error = filp->f_op->fasync(fd, filp, on);
551
		else
552 553
			error = -ENOTTY;
	}
554
	return error < 0 ? error : 0;
555 556
}

557 558
static int ioctl_fsfreeze(struct file *filp)
{
Al Viro's avatar
Al Viro committed
559
	struct super_block *sb = file_inode(filp)->i_sb;
560

561
	if (!ns_capable(sb->s_user_ns, CAP_SYS_ADMIN))
562 563 564
		return -EPERM;

	/* If filesystem doesn't support freeze feature, return. */
565
	if (sb->s_op->freeze_fs == NULL && sb->s_op->freeze_super == NULL)
566 567 568
		return -EOPNOTSUPP;

	/* Freeze */
569 570
	if (sb->s_op->freeze_super)
		return sb->s_op->freeze_super(sb);
571
	return freeze_super(sb);
572 573 574 575
}

static int ioctl_fsthaw(struct file *filp)
{
Al Viro's avatar
Al Viro committed
576
	struct super_block *sb = file_inode(filp)->i_sb;
577

578
	if (!ns_capable(sb->s_user_ns, CAP_SYS_ADMIN))
579 580 581
		return -EPERM;

	/* Thaw */
582 583
	if (sb->s_op->thaw_super)
		return sb->s_op->thaw_super(sb);
584
	return thaw_super(sb);
585 586
}

587
static int ioctl_file_dedupe_range(struct file *file, void __user *arg)
588 589 590 591 592 593 594 595 596 597 598 599 600
{
	struct file_dedupe_range __user *argp = arg;
	struct file_dedupe_range *same = NULL;
	int ret;
	unsigned long size;
	u16 count;

	if (get_user(count, &argp->dest_count)) {
		ret = -EFAULT;
		goto out;
	}

	size = offsetof(struct file_dedupe_range __user, info[count]);
601 602 603 604
	if (size > PAGE_SIZE) {
		ret = -ENOMEM;
		goto out;
	}
605 606 607 608 609 610 611 612

	same = memdup_user(argp, size);
	if (IS_ERR(same)) {
		ret = PTR_ERR(same);
		same = NULL;
		goto out;
	}

613
	same->dest_count = count;
614 615 616 617 618 619 620 621 622 623 624 625 626
	ret = vfs_dedupe_file_range(file, same);
	if (ret)
		goto out;

	ret = copy_to_user(argp, same, size);
	if (ret)
		ret = -EFAULT;

out:
	kfree(same);
	return ret;
}

Linus Torvalds's avatar
Linus Torvalds committed
627 628 629 630
/*
 * When you add any new common ioctls to the switches above and below
 * please update compat_sys_ioctl() too.
 *
631
 * do_vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d.
Linus Torvalds's avatar
Linus Torvalds committed
632 633
 * It's just a simple helper for sys_ioctl and compat_sys_ioctl.
 */
634 635
int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd,
	     unsigned long arg)
Linus Torvalds's avatar
Linus Torvalds committed
636
{
637 638
	int error = 0;
	int __user *argp = (int __user *)arg;
Al Viro's avatar
Al Viro committed
639
	struct inode *inode = file_inode(filp);
Linus Torvalds's avatar
Linus Torvalds committed
640 641

	switch (cmd) {
642 643 644
	case FIOCLEX:
		set_close_on_exec(fd, 1);
		break;
Linus Torvalds's avatar
Linus Torvalds committed
645

646 647 648
	case FIONCLEX:
		set_close_on_exec(fd, 0);
		break;
Linus Torvalds's avatar
Linus Torvalds committed
649

650
	case FIONBIO:
651
		error = ioctl_fionbio(filp, argp);
652 653 654
		break;

	case FIOASYNC:
655
		error = ioctl_fioasync(fd, filp, argp);
656 657 658
		break;

	case FIOQSIZE:
659 660 661 662 663
		if (S_ISDIR(inode->i_mode) || S_ISREG(inode->i_mode) ||
		    S_ISLNK(inode->i_mode)) {
			loff_t res = inode_get_bytes(inode);
			error = copy_to_user(argp, &res, sizeof(res)) ?
					-EFAULT : 0;
664 665 666
		} else
			error = -ENOTTY;
		break;
667 668 669 670 671 672 673 674 675

	case FIFREEZE:
		error = ioctl_fsfreeze(filp);
		break;

	case FITHAW:
		error = ioctl_fsthaw(filp);
		break;

676 677 678 679
	case FS_IOC_FIEMAP:
		return ioctl_fiemap(filp, arg);

	case FIGETBSZ:
680 681 682
		/* anon_bdev filesystems may not have a block size */
		if (!inode->i_sb->s_blocksize)
			return -EINVAL;
683
		return put_user(inode->i_sb->s_blocksize, argp);
684

685 686 687 688 689 690
	case FICLONE:
		return ioctl_file_clone(filp, arg, 0, 0, 0);

	case FICLONERANGE:
		return ioctl_file_clone_range(filp, argp);

691 692 693
	case FIDEDUPERANGE:
		return ioctl_file_dedupe_range(filp, argp);

694
	default:
695
		if (S_ISREG(inode->i_mode))
696 697
			error = file_ioctl(filp, cmd, arg);
		else
698
			error = vfs_ioctl(filp, cmd, arg);
699
		break;
Linus Torvalds's avatar
Linus Torvalds committed
700 701 702 703
	}
	return error;
}

704
int ksys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
Linus Torvalds's avatar
Linus Torvalds committed
705
{
706 707 708 709 710 711 712 713 714
	int error;
	struct fd f = fdget(fd);

	if (!f.file)
		return -EBADF;
	error = security_file_ioctl(f.file, cmd, arg);
	if (!error)
		error = do_vfs_ioctl(f.file, fd, cmd, arg);
	fdput(f);
Linus Torvalds's avatar
Linus Torvalds committed
715 716
	return error;
}
717 718 719 720 721

SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, unsigned long, arg)
{
	return ksys_ioctl(fd, cmd, arg);
}