1 /* 2 * linux/fs/ext4/ioctl.c 3 * 4 * Copyright (C) 1993, 1994, 1995 5 * Remy Card (card@masi.ibp.fr) 6 * Laboratoire MASI - Institut Blaise Pascal 7 * Universite Pierre et Marie Curie (Paris VI) 8 */ 9 10 #include <linux/fs.h> 11 #include <linux/jbd2.h> 12 #include <linux/capability.h> 13 #include <linux/time.h> 14 #include <linux/compat.h> 15 #include <linux/mount.h> 16 #include <linux/file.h> 17 #include <asm/uaccess.h> 18 #include "ext4_jbd2.h" 19 #include "ext4.h" 20 21 #define MAX_32_NUM ((((unsigned long long) 1) << 32) - 1) 22 23 /** 24 * Swap memory between @a and @b for @len bytes. 25 * 26 * @a: pointer to first memory area 27 * @b: pointer to second memory area 28 * @len: number of bytes to swap 29 * 30 */ 31 static void memswap(void *a, void *b, size_t len) 32 { 33 unsigned char *ap, *bp; 34 unsigned char tmp; 35 36 ap = (unsigned char *)a; 37 bp = (unsigned char *)b; 38 while (len-- > 0) { 39 tmp = *ap; 40 *ap = *bp; 41 *bp = tmp; 42 ap++; 43 bp++; 44 } 45 } 46 47 /** 48 * Swap i_data and associated attributes between @inode1 and @inode2. 49 * This function is used for the primary swap between inode1 and inode2 50 * and also to revert this primary swap in case of errors. 51 * 52 * Therefore you have to make sure, that calling this method twice 53 * will revert all changes. 54 * 55 * @inode1: pointer to first inode 56 * @inode2: pointer to second inode 57 */ 58 static void swap_inode_data(struct inode *inode1, struct inode *inode2) 59 { 60 loff_t isize; 61 struct ext4_inode_info *ei1; 62 struct ext4_inode_info *ei2; 63 64 ei1 = EXT4_I(inode1); 65 ei2 = EXT4_I(inode2); 66 67 memswap(&inode1->i_flags, &inode2->i_flags, sizeof(inode1->i_flags)); 68 memswap(&inode1->i_version, &inode2->i_version, 69 sizeof(inode1->i_version)); 70 memswap(&inode1->i_blocks, &inode2->i_blocks, 71 sizeof(inode1->i_blocks)); 72 memswap(&inode1->i_bytes, &inode2->i_bytes, sizeof(inode1->i_bytes)); 73 memswap(&inode1->i_atime, &inode2->i_atime, sizeof(inode1->i_atime)); 74 memswap(&inode1->i_mtime, &inode2->i_mtime, sizeof(inode1->i_mtime)); 75 76 memswap(ei1->i_data, ei2->i_data, sizeof(ei1->i_data)); 77 memswap(&ei1->i_flags, &ei2->i_flags, sizeof(ei1->i_flags)); 78 memswap(&ei1->i_disksize, &ei2->i_disksize, sizeof(ei1->i_disksize)); 79 ext4_es_remove_extent(inode1, 0, EXT_MAX_BLOCKS); 80 ext4_es_remove_extent(inode2, 0, EXT_MAX_BLOCKS); 81 ext4_es_lru_del(inode1); 82 ext4_es_lru_del(inode2); 83 84 isize = i_size_read(inode1); 85 i_size_write(inode1, i_size_read(inode2)); 86 i_size_write(inode2, isize); 87 } 88 89 /** 90 * Swap the information from the given @inode and the inode 91 * EXT4_BOOT_LOADER_INO. It will basically swap i_data and all other 92 * important fields of the inodes. 93 * 94 * @sb: the super block of the filesystem 95 * @inode: the inode to swap with EXT4_BOOT_LOADER_INO 96 * 97 */ 98 static long swap_inode_boot_loader(struct super_block *sb, 99 struct inode *inode) 100 { 101 handle_t *handle; 102 int err; 103 struct inode *inode_bl; 104 struct ext4_inode_info *ei_bl; 105 struct ext4_sb_info *sbi = EXT4_SB(sb); 106 107 if (inode->i_nlink != 1 || !S_ISREG(inode->i_mode)) { 108 err = -EINVAL; 109 goto swap_boot_out; 110 } 111 112 if (!inode_owner_or_capable(inode) || !capable(CAP_SYS_ADMIN)) { 113 err = -EPERM; 114 goto swap_boot_out; 115 } 116 117 inode_bl = ext4_iget(sb, EXT4_BOOT_LOADER_INO); 118 if (IS_ERR(inode_bl)) { 119 err = PTR_ERR(inode_bl); 120 goto swap_boot_out; 121 } 122 ei_bl = EXT4_I(inode_bl); 123 124 filemap_flush(inode->i_mapping); 125 filemap_flush(inode_bl->i_mapping); 126 127 /* Protect orig inodes against a truncate and make sure, 128 * that only 1 swap_inode_boot_loader is running. */ 129 lock_two_nondirectories(inode, inode_bl); 130 131 truncate_inode_pages(&inode->i_data, 0); 132 truncate_inode_pages(&inode_bl->i_data, 0); 133 134 /* Wait for all existing dio workers */ 135 ext4_inode_block_unlocked_dio(inode); 136 ext4_inode_block_unlocked_dio(inode_bl); 137 inode_dio_wait(inode); 138 inode_dio_wait(inode_bl); 139 140 handle = ext4_journal_start(inode_bl, EXT4_HT_MOVE_EXTENTS, 2); 141 if (IS_ERR(handle)) { 142 err = -EINVAL; 143 goto journal_err_out; 144 } 145 146 /* Protect extent tree against block allocations via delalloc */ 147 ext4_double_down_write_data_sem(inode, inode_bl); 148 149 if (inode_bl->i_nlink == 0) { 150 /* this inode has never been used as a BOOT_LOADER */ 151 set_nlink(inode_bl, 1); 152 i_uid_write(inode_bl, 0); 153 i_gid_write(inode_bl, 0); 154 inode_bl->i_flags = 0; 155 ei_bl->i_flags = 0; 156 inode_bl->i_version = 1; 157 i_size_write(inode_bl, 0); 158 inode_bl->i_mode = S_IFREG; 159 if (EXT4_HAS_INCOMPAT_FEATURE(sb, 160 EXT4_FEATURE_INCOMPAT_EXTENTS)) { 161 ext4_set_inode_flag(inode_bl, EXT4_INODE_EXTENTS); 162 ext4_ext_tree_init(handle, inode_bl); 163 } else 164 memset(ei_bl->i_data, 0, sizeof(ei_bl->i_data)); 165 } 166 167 swap_inode_data(inode, inode_bl); 168 169 inode->i_ctime = inode_bl->i_ctime = ext4_current_time(inode); 170 171 spin_lock(&sbi->s_next_gen_lock); 172 inode->i_generation = sbi->s_next_generation++; 173 inode_bl->i_generation = sbi->s_next_generation++; 174 spin_unlock(&sbi->s_next_gen_lock); 175 176 ext4_discard_preallocations(inode); 177 178 err = ext4_mark_inode_dirty(handle, inode); 179 if (err < 0) { 180 ext4_warning(inode->i_sb, 181 "couldn't mark inode #%lu dirty (err %d)", 182 inode->i_ino, err); 183 /* Revert all changes: */ 184 swap_inode_data(inode, inode_bl); 185 } else { 186 err = ext4_mark_inode_dirty(handle, inode_bl); 187 if (err < 0) { 188 ext4_warning(inode_bl->i_sb, 189 "couldn't mark inode #%lu dirty (err %d)", 190 inode_bl->i_ino, err); 191 /* Revert all changes: */ 192 swap_inode_data(inode, inode_bl); 193 ext4_mark_inode_dirty(handle, inode); 194 } 195 } 196 197 ext4_journal_stop(handle); 198 199 ext4_double_up_write_data_sem(inode, inode_bl); 200 201 journal_err_out: 202 ext4_inode_resume_unlocked_dio(inode); 203 ext4_inode_resume_unlocked_dio(inode_bl); 204 205 unlock_two_nondirectories(inode, inode_bl); 206 207 iput(inode_bl); 208 209 swap_boot_out: 210 return err; 211 } 212 213 long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 214 { 215 struct inode *inode = file_inode(filp); 216 struct super_block *sb = inode->i_sb; 217 struct ext4_inode_info *ei = EXT4_I(inode); 218 unsigned int flags; 219 220 ext4_debug("cmd = %u, arg = %lu\n", cmd, arg); 221 222 switch (cmd) { 223 case EXT4_IOC_GETFLAGS: 224 ext4_get_inode_flags(ei); 225 flags = ei->i_flags & EXT4_FL_USER_VISIBLE; 226 return put_user(flags, (int __user *) arg); 227 case EXT4_IOC_SETFLAGS: { 228 handle_t *handle = NULL; 229 int err, migrate = 0; 230 struct ext4_iloc iloc; 231 unsigned int oldflags, mask, i; 232 unsigned int jflag; 233 234 if (!inode_owner_or_capable(inode)) 235 return -EACCES; 236 237 if (get_user(flags, (int __user *) arg)) 238 return -EFAULT; 239 240 err = mnt_want_write_file(filp); 241 if (err) 242 return err; 243 244 flags = ext4_mask_flags(inode->i_mode, flags); 245 246 err = -EPERM; 247 mutex_lock(&inode->i_mutex); 248 /* Is it quota file? Do not allow user to mess with it */ 249 if (IS_NOQUOTA(inode)) 250 goto flags_out; 251 252 oldflags = ei->i_flags; 253 254 /* The JOURNAL_DATA flag is modifiable only by root */ 255 jflag = flags & EXT4_JOURNAL_DATA_FL; 256 257 /* 258 * The IMMUTABLE and APPEND_ONLY flags can only be changed by 259 * the relevant capability. 260 * 261 * This test looks nicer. Thanks to Pauline Middelink 262 */ 263 if ((flags ^ oldflags) & (EXT4_APPEND_FL | EXT4_IMMUTABLE_FL)) { 264 if (!capable(CAP_LINUX_IMMUTABLE)) 265 goto flags_out; 266 } 267 268 /* 269 * The JOURNAL_DATA flag can only be changed by 270 * the relevant capability. 271 */ 272 if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) { 273 if (!capable(CAP_SYS_RESOURCE)) 274 goto flags_out; 275 } 276 if ((flags ^ oldflags) & EXT4_EXTENTS_FL) 277 migrate = 1; 278 279 if (flags & EXT4_EOFBLOCKS_FL) { 280 /* we don't support adding EOFBLOCKS flag */ 281 if (!(oldflags & EXT4_EOFBLOCKS_FL)) { 282 err = -EOPNOTSUPP; 283 goto flags_out; 284 } 285 } else if (oldflags & EXT4_EOFBLOCKS_FL) 286 ext4_truncate(inode); 287 288 handle = ext4_journal_start(inode, EXT4_HT_INODE, 1); 289 if (IS_ERR(handle)) { 290 err = PTR_ERR(handle); 291 goto flags_out; 292 } 293 if (IS_SYNC(inode)) 294 ext4_handle_sync(handle); 295 err = ext4_reserve_inode_write(handle, inode, &iloc); 296 if (err) 297 goto flags_err; 298 299 for (i = 0, mask = 1; i < 32; i++, mask <<= 1) { 300 if (!(mask & EXT4_FL_USER_MODIFIABLE)) 301 continue; 302 if (mask & flags) 303 ext4_set_inode_flag(inode, i); 304 else 305 ext4_clear_inode_flag(inode, i); 306 } 307 308 ext4_set_inode_flags(inode); 309 inode->i_ctime = ext4_current_time(inode); 310 311 err = ext4_mark_iloc_dirty(handle, inode, &iloc); 312 flags_err: 313 ext4_journal_stop(handle); 314 if (err) 315 goto flags_out; 316 317 if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) 318 err = ext4_change_inode_journal_flag(inode, jflag); 319 if (err) 320 goto flags_out; 321 if (migrate) { 322 if (flags & EXT4_EXTENTS_FL) 323 err = ext4_ext_migrate(inode); 324 else 325 err = ext4_ind_migrate(inode); 326 } 327 328 flags_out: 329 mutex_unlock(&inode->i_mutex); 330 mnt_drop_write_file(filp); 331 return err; 332 } 333 case EXT4_IOC_GETVERSION: 334 case EXT4_IOC_GETVERSION_OLD: 335 return put_user(inode->i_generation, (int __user *) arg); 336 case EXT4_IOC_SETVERSION: 337 case EXT4_IOC_SETVERSION_OLD: { 338 handle_t *handle; 339 struct ext4_iloc iloc; 340 __u32 generation; 341 int err; 342 343 if (!inode_owner_or_capable(inode)) 344 return -EPERM; 345 346 if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, 347 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) { 348 ext4_warning(sb, "Setting inode version is not " 349 "supported with metadata_csum enabled."); 350 return -ENOTTY; 351 } 352 353 err = mnt_want_write_file(filp); 354 if (err) 355 return err; 356 if (get_user(generation, (int __user *) arg)) { 357 err = -EFAULT; 358 goto setversion_out; 359 } 360 361 mutex_lock(&inode->i_mutex); 362 handle = ext4_journal_start(inode, EXT4_HT_INODE, 1); 363 if (IS_ERR(handle)) { 364 err = PTR_ERR(handle); 365 goto unlock_out; 366 } 367 err = ext4_reserve_inode_write(handle, inode, &iloc); 368 if (err == 0) { 369 inode->i_ctime = ext4_current_time(inode); 370 inode->i_generation = generation; 371 err = ext4_mark_iloc_dirty(handle, inode, &iloc); 372 } 373 ext4_journal_stop(handle); 374 375 unlock_out: 376 mutex_unlock(&inode->i_mutex); 377 setversion_out: 378 mnt_drop_write_file(filp); 379 return err; 380 } 381 case EXT4_IOC_GROUP_EXTEND: { 382 ext4_fsblk_t n_blocks_count; 383 int err, err2=0; 384 385 err = ext4_resize_begin(sb); 386 if (err) 387 return err; 388 389 if (get_user(n_blocks_count, (__u32 __user *)arg)) { 390 err = -EFAULT; 391 goto group_extend_out; 392 } 393 394 if (EXT4_HAS_RO_COMPAT_FEATURE(sb, 395 EXT4_FEATURE_RO_COMPAT_BIGALLOC)) { 396 ext4_msg(sb, KERN_ERR, 397 "Online resizing not supported with bigalloc"); 398 err = -EOPNOTSUPP; 399 goto group_extend_out; 400 } 401 402 err = mnt_want_write_file(filp); 403 if (err) 404 goto group_extend_out; 405 406 err = ext4_group_extend(sb, EXT4_SB(sb)->s_es, n_blocks_count); 407 if (EXT4_SB(sb)->s_journal) { 408 jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); 409 err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal); 410 jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); 411 } 412 if (err == 0) 413 err = err2; 414 mnt_drop_write_file(filp); 415 group_extend_out: 416 ext4_resize_end(sb); 417 return err; 418 } 419 420 case EXT4_IOC_MOVE_EXT: { 421 struct move_extent me; 422 struct fd donor; 423 int err; 424 425 if (!(filp->f_mode & FMODE_READ) || 426 !(filp->f_mode & FMODE_WRITE)) 427 return -EBADF; 428 429 if (copy_from_user(&me, 430 (struct move_extent __user *)arg, sizeof(me))) 431 return -EFAULT; 432 me.moved_len = 0; 433 434 donor = fdget(me.donor_fd); 435 if (!donor.file) 436 return -EBADF; 437 438 if (!(donor.file->f_mode & FMODE_WRITE)) { 439 err = -EBADF; 440 goto mext_out; 441 } 442 443 if (EXT4_HAS_RO_COMPAT_FEATURE(sb, 444 EXT4_FEATURE_RO_COMPAT_BIGALLOC)) { 445 ext4_msg(sb, KERN_ERR, 446 "Online defrag not supported with bigalloc"); 447 err = -EOPNOTSUPP; 448 goto mext_out; 449 } 450 451 err = mnt_want_write_file(filp); 452 if (err) 453 goto mext_out; 454 455 err = ext4_move_extents(filp, donor.file, me.orig_start, 456 me.donor_start, me.len, &me.moved_len); 457 mnt_drop_write_file(filp); 458 459 if (copy_to_user((struct move_extent __user *)arg, 460 &me, sizeof(me))) 461 err = -EFAULT; 462 mext_out: 463 fdput(donor); 464 return err; 465 } 466 467 case EXT4_IOC_GROUP_ADD: { 468 struct ext4_new_group_data input; 469 int err, err2=0; 470 471 err = ext4_resize_begin(sb); 472 if (err) 473 return err; 474 475 if (copy_from_user(&input, (struct ext4_new_group_input __user *)arg, 476 sizeof(input))) { 477 err = -EFAULT; 478 goto group_add_out; 479 } 480 481 if (EXT4_HAS_RO_COMPAT_FEATURE(sb, 482 EXT4_FEATURE_RO_COMPAT_BIGALLOC)) { 483 ext4_msg(sb, KERN_ERR, 484 "Online resizing not supported with bigalloc"); 485 err = -EOPNOTSUPP; 486 goto group_add_out; 487 } 488 489 err = mnt_want_write_file(filp); 490 if (err) 491 goto group_add_out; 492 493 err = ext4_group_add(sb, &input); 494 if (EXT4_SB(sb)->s_journal) { 495 jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); 496 err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal); 497 jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); 498 } 499 if (err == 0) 500 err = err2; 501 mnt_drop_write_file(filp); 502 if (!err && ext4_has_group_desc_csum(sb) && 503 test_opt(sb, INIT_INODE_TABLE)) 504 err = ext4_register_li_request(sb, input.group); 505 group_add_out: 506 ext4_resize_end(sb); 507 return err; 508 } 509 510 case EXT4_IOC_MIGRATE: 511 { 512 int err; 513 if (!inode_owner_or_capable(inode)) 514 return -EACCES; 515 516 err = mnt_want_write_file(filp); 517 if (err) 518 return err; 519 /* 520 * inode_mutex prevent write and truncate on the file. 521 * Read still goes through. We take i_data_sem in 522 * ext4_ext_swap_inode_data before we switch the 523 * inode format to prevent read. 524 */ 525 mutex_lock(&(inode->i_mutex)); 526 err = ext4_ext_migrate(inode); 527 mutex_unlock(&(inode->i_mutex)); 528 mnt_drop_write_file(filp); 529 return err; 530 } 531 532 case EXT4_IOC_ALLOC_DA_BLKS: 533 { 534 int err; 535 if (!inode_owner_or_capable(inode)) 536 return -EACCES; 537 538 err = mnt_want_write_file(filp); 539 if (err) 540 return err; 541 err = ext4_alloc_da_blocks(inode); 542 mnt_drop_write_file(filp); 543 return err; 544 } 545 546 case EXT4_IOC_SWAP_BOOT: 547 if (!(filp->f_mode & FMODE_WRITE)) 548 return -EBADF; 549 return swap_inode_boot_loader(sb, inode); 550 551 case EXT4_IOC_RESIZE_FS: { 552 ext4_fsblk_t n_blocks_count; 553 int err = 0, err2 = 0; 554 ext4_group_t o_group = EXT4_SB(sb)->s_groups_count; 555 556 if (EXT4_HAS_RO_COMPAT_FEATURE(sb, 557 EXT4_FEATURE_RO_COMPAT_BIGALLOC)) { 558 ext4_msg(sb, KERN_ERR, 559 "Online resizing not (yet) supported with bigalloc"); 560 return -EOPNOTSUPP; 561 } 562 563 if (copy_from_user(&n_blocks_count, (__u64 __user *)arg, 564 sizeof(__u64))) { 565 return -EFAULT; 566 } 567 568 err = ext4_resize_begin(sb); 569 if (err) 570 return err; 571 572 err = mnt_want_write_file(filp); 573 if (err) 574 goto resizefs_out; 575 576 err = ext4_resize_fs(sb, n_blocks_count); 577 if (EXT4_SB(sb)->s_journal) { 578 jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); 579 err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal); 580 jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); 581 } 582 if (err == 0) 583 err = err2; 584 mnt_drop_write_file(filp); 585 if (!err && (o_group > EXT4_SB(sb)->s_groups_count) && 586 ext4_has_group_desc_csum(sb) && 587 test_opt(sb, INIT_INODE_TABLE)) 588 err = ext4_register_li_request(sb, o_group); 589 590 resizefs_out: 591 ext4_resize_end(sb); 592 return err; 593 } 594 595 case FITRIM: 596 { 597 struct request_queue *q = bdev_get_queue(sb->s_bdev); 598 struct fstrim_range range; 599 int ret = 0; 600 601 if (!capable(CAP_SYS_ADMIN)) 602 return -EPERM; 603 604 if (!blk_queue_discard(q)) 605 return -EOPNOTSUPP; 606 607 if (copy_from_user(&range, (struct fstrim_range __user *)arg, 608 sizeof(range))) 609 return -EFAULT; 610 611 range.minlen = max((unsigned int)range.minlen, 612 q->limits.discard_granularity); 613 ret = ext4_trim_fs(sb, &range); 614 if (ret < 0) 615 return ret; 616 617 if (copy_to_user((struct fstrim_range __user *)arg, &range, 618 sizeof(range))) 619 return -EFAULT; 620 621 return 0; 622 } 623 case EXT4_IOC_PRECACHE_EXTENTS: 624 return ext4_ext_precache(inode); 625 626 default: 627 return -ENOTTY; 628 } 629 } 630 631 #ifdef CONFIG_COMPAT 632 long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 633 { 634 /* These are just misnamed, they actually get/put from/to user an int */ 635 switch (cmd) { 636 case EXT4_IOC32_GETFLAGS: 637 cmd = EXT4_IOC_GETFLAGS; 638 break; 639 case EXT4_IOC32_SETFLAGS: 640 cmd = EXT4_IOC_SETFLAGS; 641 break; 642 case EXT4_IOC32_GETVERSION: 643 cmd = EXT4_IOC_GETVERSION; 644 break; 645 case EXT4_IOC32_SETVERSION: 646 cmd = EXT4_IOC_SETVERSION; 647 break; 648 case EXT4_IOC32_GROUP_EXTEND: 649 cmd = EXT4_IOC_GROUP_EXTEND; 650 break; 651 case EXT4_IOC32_GETVERSION_OLD: 652 cmd = EXT4_IOC_GETVERSION_OLD; 653 break; 654 case EXT4_IOC32_SETVERSION_OLD: 655 cmd = EXT4_IOC_SETVERSION_OLD; 656 break; 657 case EXT4_IOC32_GETRSVSZ: 658 cmd = EXT4_IOC_GETRSVSZ; 659 break; 660 case EXT4_IOC32_SETRSVSZ: 661 cmd = EXT4_IOC_SETRSVSZ; 662 break; 663 case EXT4_IOC32_GROUP_ADD: { 664 struct compat_ext4_new_group_input __user *uinput; 665 struct ext4_new_group_input input; 666 mm_segment_t old_fs; 667 int err; 668 669 uinput = compat_ptr(arg); 670 err = get_user(input.group, &uinput->group); 671 err |= get_user(input.block_bitmap, &uinput->block_bitmap); 672 err |= get_user(input.inode_bitmap, &uinput->inode_bitmap); 673 err |= get_user(input.inode_table, &uinput->inode_table); 674 err |= get_user(input.blocks_count, &uinput->blocks_count); 675 err |= get_user(input.reserved_blocks, 676 &uinput->reserved_blocks); 677 if (err) 678 return -EFAULT; 679 old_fs = get_fs(); 680 set_fs(KERNEL_DS); 681 err = ext4_ioctl(file, EXT4_IOC_GROUP_ADD, 682 (unsigned long) &input); 683 set_fs(old_fs); 684 return err; 685 } 686 case EXT4_IOC_MOVE_EXT: 687 case FITRIM: 688 case EXT4_IOC_RESIZE_FS: 689 case EXT4_IOC_PRECACHE_EXTENTS: 690 break; 691 default: 692 return -ENOIOCTLCMD; 693 } 694 return ext4_ioctl(file, cmd, (unsigned long) compat_ptr(arg)); 695 } 696 #endif 697