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