| .. | .. |
|---|
| 86 | 86 | i_size_write(inode2, isize); |
|---|
| 87 | 87 | } |
|---|
| 88 | 88 | |
|---|
| 89 | | -static void reset_inode_seed(struct inode *inode) |
|---|
| 89 | +void ext4_reset_inode_seed(struct inode *inode) |
|---|
| 90 | 90 | { |
|---|
| 91 | 91 | struct ext4_inode_info *ei = EXT4_I(inode); |
|---|
| 92 | 92 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); |
|---|
| .. | .. |
|---|
| 121 | 121 | blkcnt_t blocks; |
|---|
| 122 | 122 | unsigned short bytes; |
|---|
| 123 | 123 | |
|---|
| 124 | | - inode_bl = ext4_iget(sb, EXT4_BOOT_LOADER_INO, EXT4_IGET_SPECIAL); |
|---|
| 124 | + inode_bl = ext4_iget(sb, EXT4_BOOT_LOADER_INO, |
|---|
| 125 | + EXT4_IGET_SPECIAL | EXT4_IGET_BAD); |
|---|
| 125 | 126 | if (IS_ERR(inode_bl)) |
|---|
| 126 | 127 | return PTR_ERR(inode_bl); |
|---|
| 127 | 128 | ei_bl = EXT4_I(inode_bl); |
|---|
| .. | .. |
|---|
| 165 | 166 | err = -EINVAL; |
|---|
| 166 | 167 | goto err_out; |
|---|
| 167 | 168 | } |
|---|
| 169 | + ext4_fc_start_ineligible(sb, EXT4_FC_REASON_SWAP_BOOT); |
|---|
| 168 | 170 | |
|---|
| 169 | 171 | /* Protect extent tree against block allocations via delalloc */ |
|---|
| 170 | 172 | ext4_double_down_write_data_sem(inode, inode_bl); |
|---|
| 171 | 173 | |
|---|
| 172 | | - if (inode_bl->i_nlink == 0) { |
|---|
| 174 | + if (is_bad_inode(inode_bl) || !S_ISREG(inode_bl->i_mode)) { |
|---|
| 173 | 175 | /* this inode has never been used as a BOOT_LOADER */ |
|---|
| 174 | 176 | set_nlink(inode_bl, 1); |
|---|
| 175 | 177 | i_uid_write(inode_bl, 0); |
|---|
| .. | .. |
|---|
| 178 | 180 | ei_bl->i_flags = 0; |
|---|
| 179 | 181 | inode_set_iversion(inode_bl, 1); |
|---|
| 180 | 182 | i_size_write(inode_bl, 0); |
|---|
| 183 | + EXT4_I(inode_bl)->i_disksize = inode_bl->i_size; |
|---|
| 181 | 184 | inode_bl->i_mode = S_IFREG; |
|---|
| 182 | 185 | if (ext4_has_feature_extents(sb)) { |
|---|
| 183 | 186 | ext4_set_inode_flag(inode_bl, EXT4_INODE_EXTENTS); |
|---|
| .. | .. |
|---|
| 199 | 202 | |
|---|
| 200 | 203 | inode->i_generation = prandom_u32(); |
|---|
| 201 | 204 | inode_bl->i_generation = prandom_u32(); |
|---|
| 202 | | - reset_inode_seed(inode); |
|---|
| 203 | | - reset_inode_seed(inode_bl); |
|---|
| 205 | + ext4_reset_inode_seed(inode); |
|---|
| 206 | + ext4_reset_inode_seed(inode_bl); |
|---|
| 204 | 207 | |
|---|
| 205 | | - ext4_discard_preallocations(inode); |
|---|
| 208 | + ext4_discard_preallocations(inode, 0); |
|---|
| 206 | 209 | |
|---|
| 207 | 210 | err = ext4_mark_inode_dirty(handle, inode); |
|---|
| 208 | 211 | if (err < 0) { |
|---|
| .. | .. |
|---|
| 247 | 250 | |
|---|
| 248 | 251 | err_out1: |
|---|
| 249 | 252 | ext4_journal_stop(handle); |
|---|
| 253 | + ext4_fc_stop_ineligible(sb); |
|---|
| 250 | 254 | ext4_double_up_write_data_sem(inode, inode_bl); |
|---|
| 251 | 255 | |
|---|
| 252 | 256 | err_out: |
|---|
| .. | .. |
|---|
| 292 | 296 | return 0; |
|---|
| 293 | 297 | } |
|---|
| 294 | 298 | |
|---|
| 299 | +static void ext4_dax_dontcache(struct inode *inode, unsigned int flags) |
|---|
| 300 | +{ |
|---|
| 301 | + struct ext4_inode_info *ei = EXT4_I(inode); |
|---|
| 302 | + |
|---|
| 303 | + if (S_ISDIR(inode->i_mode)) |
|---|
| 304 | + return; |
|---|
| 305 | + |
|---|
| 306 | + if (test_opt2(inode->i_sb, DAX_NEVER) || |
|---|
| 307 | + test_opt(inode->i_sb, DAX_ALWAYS)) |
|---|
| 308 | + return; |
|---|
| 309 | + |
|---|
| 310 | + if ((ei->i_flags ^ flags) & EXT4_DAX_FL) |
|---|
| 311 | + d_mark_dontcache(inode); |
|---|
| 312 | +} |
|---|
| 313 | + |
|---|
| 314 | +static bool dax_compatible(struct inode *inode, unsigned int oldflags, |
|---|
| 315 | + unsigned int flags) |
|---|
| 316 | +{ |
|---|
| 317 | + /* Allow the DAX flag to be changed on inline directories */ |
|---|
| 318 | + if (S_ISDIR(inode->i_mode)) { |
|---|
| 319 | + flags &= ~EXT4_INLINE_DATA_FL; |
|---|
| 320 | + oldflags &= ~EXT4_INLINE_DATA_FL; |
|---|
| 321 | + } |
|---|
| 322 | + |
|---|
| 323 | + if (flags & EXT4_DAX_FL) { |
|---|
| 324 | + if ((oldflags & EXT4_DAX_MUT_EXCL) || |
|---|
| 325 | + ext4_test_inode_state(inode, |
|---|
| 326 | + EXT4_STATE_VERITY_IN_PROGRESS)) { |
|---|
| 327 | + return false; |
|---|
| 328 | + } |
|---|
| 329 | + } |
|---|
| 330 | + |
|---|
| 331 | + if ((flags & EXT4_DAX_MUT_EXCL) && (oldflags & EXT4_DAX_FL)) |
|---|
| 332 | + return false; |
|---|
| 333 | + |
|---|
| 334 | + return true; |
|---|
| 335 | +} |
|---|
| 336 | + |
|---|
| 295 | 337 | static int ext4_ioctl_setflags(struct inode *inode, |
|---|
| 296 | 338 | unsigned int flags) |
|---|
| 297 | 339 | { |
|---|
| .. | .. |
|---|
| 300 | 342 | int err = -EPERM, migrate = 0; |
|---|
| 301 | 343 | struct ext4_iloc iloc; |
|---|
| 302 | 344 | unsigned int oldflags, mask, i; |
|---|
| 303 | | - unsigned int jflag; |
|---|
| 304 | 345 | struct super_block *sb = inode->i_sb; |
|---|
| 305 | 346 | |
|---|
| 306 | 347 | /* Is it quota file? Do not allow user to mess with it */ |
|---|
| .. | .. |
|---|
| 309 | 350 | |
|---|
| 310 | 351 | oldflags = ei->i_flags; |
|---|
| 311 | 352 | |
|---|
| 312 | | - /* The JOURNAL_DATA flag is modifiable only by root */ |
|---|
| 313 | | - jflag = flags & EXT4_JOURNAL_DATA_FL; |
|---|
| 314 | | - |
|---|
| 315 | | - /* |
|---|
| 316 | | - * The IMMUTABLE and APPEND_ONLY flags can only be changed by |
|---|
| 317 | | - * the relevant capability. |
|---|
| 318 | | - * |
|---|
| 319 | | - * This test looks nicer. Thanks to Pauline Middelink |
|---|
| 320 | | - */ |
|---|
| 321 | | - if ((flags ^ oldflags) & (EXT4_APPEND_FL | EXT4_IMMUTABLE_FL)) { |
|---|
| 322 | | - if (!capable(CAP_LINUX_IMMUTABLE)) |
|---|
| 323 | | - goto flags_out; |
|---|
| 324 | | - } |
|---|
| 353 | + err = vfs_ioc_setflags_prepare(inode, oldflags, flags); |
|---|
| 354 | + if (err) |
|---|
| 355 | + goto flags_out; |
|---|
| 325 | 356 | |
|---|
| 326 | 357 | /* |
|---|
| 327 | 358 | * The JOURNAL_DATA flag can only be changed by |
|---|
| 328 | 359 | * the relevant capability. |
|---|
| 329 | 360 | */ |
|---|
| 330 | | - if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) { |
|---|
| 361 | + if ((flags ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) { |
|---|
| 331 | 362 | if (!capable(CAP_SYS_RESOURCE)) |
|---|
| 332 | 363 | goto flags_out; |
|---|
| 333 | 364 | } |
|---|
| 365 | + |
|---|
| 366 | + if (!dax_compatible(inode, oldflags, flags)) { |
|---|
| 367 | + err = -EOPNOTSUPP; |
|---|
| 368 | + goto flags_out; |
|---|
| 369 | + } |
|---|
| 370 | + |
|---|
| 334 | 371 | if ((flags ^ oldflags) & EXT4_EXTENTS_FL) |
|---|
| 335 | 372 | migrate = 1; |
|---|
| 336 | | - |
|---|
| 337 | | - if (flags & EXT4_EOFBLOCKS_FL) { |
|---|
| 338 | | - /* we don't support adding EOFBLOCKS flag */ |
|---|
| 339 | | - if (!(oldflags & EXT4_EOFBLOCKS_FL)) { |
|---|
| 340 | | - err = -EOPNOTSUPP; |
|---|
| 341 | | - goto flags_out; |
|---|
| 342 | | - } |
|---|
| 343 | | - } else if (oldflags & EXT4_EOFBLOCKS_FL) { |
|---|
| 344 | | - err = ext4_truncate(inode); |
|---|
| 345 | | - if (err) |
|---|
| 346 | | - goto flags_out; |
|---|
| 347 | | - } |
|---|
| 348 | 373 | |
|---|
| 349 | 374 | if ((flags ^ oldflags) & EXT4_CASEFOLD_FL) { |
|---|
| 350 | 375 | if (!ext4_has_feature_casefold(sb)) { |
|---|
| .. | .. |
|---|
| 388 | 413 | if (err) |
|---|
| 389 | 414 | goto flags_err; |
|---|
| 390 | 415 | |
|---|
| 416 | + ext4_dax_dontcache(inode, flags); |
|---|
| 417 | + |
|---|
| 391 | 418 | for (i = 0, mask = 1; i < 32; i++, mask <<= 1) { |
|---|
| 392 | 419 | if (!(mask & EXT4_FL_USER_MODIFIABLE)) |
|---|
| 393 | 420 | continue; |
|---|
| .. | .. |
|---|
| 400 | 427 | ext4_clear_inode_flag(inode, i); |
|---|
| 401 | 428 | } |
|---|
| 402 | 429 | |
|---|
| 403 | | - ext4_set_inode_flags(inode); |
|---|
| 430 | + ext4_set_inode_flags(inode, false); |
|---|
| 431 | + |
|---|
| 404 | 432 | inode->i_ctime = current_time(inode); |
|---|
| 405 | 433 | |
|---|
| 406 | 434 | err = ext4_mark_iloc_dirty(handle, inode, &iloc); |
|---|
| .. | .. |
|---|
| 409 | 437 | if (err) |
|---|
| 410 | 438 | goto flags_out; |
|---|
| 411 | 439 | |
|---|
| 412 | | - if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) { |
|---|
| 440 | + if ((flags ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) { |
|---|
| 413 | 441 | /* |
|---|
| 414 | 442 | * Changes to the journaling mode can cause unsafe changes to |
|---|
| 415 | | - * S_DAX if we are using the DAX mount option. |
|---|
| 443 | + * S_DAX if the inode is DAX |
|---|
| 416 | 444 | */ |
|---|
| 417 | | - if (test_opt(inode->i_sb, DAX)) { |
|---|
| 445 | + if (IS_DAX(inode)) { |
|---|
| 418 | 446 | err = -EBUSY; |
|---|
| 419 | 447 | goto flags_out; |
|---|
| 420 | 448 | } |
|---|
| 421 | 449 | |
|---|
| 422 | | - err = ext4_change_inode_journal_flag(inode, jflag); |
|---|
| 450 | + err = ext4_change_inode_journal_flag(inode, |
|---|
| 451 | + flags & EXT4_JOURNAL_DATA_FL); |
|---|
| 423 | 452 | if (err) |
|---|
| 424 | 453 | goto flags_out; |
|---|
| 425 | 454 | } |
|---|
| .. | .. |
|---|
| 467 | 496 | if (ext4_is_quota_file(inode)) |
|---|
| 468 | 497 | return err; |
|---|
| 469 | 498 | |
|---|
| 499 | + err = dquot_initialize(inode); |
|---|
| 500 | + if (err) |
|---|
| 501 | + return err; |
|---|
| 502 | + |
|---|
| 470 | 503 | err = ext4_get_inode_loc(inode, &iloc); |
|---|
| 471 | 504 | if (err) |
|---|
| 472 | 505 | return err; |
|---|
| .. | .. |
|---|
| 481 | 514 | } else { |
|---|
| 482 | 515 | brelse(iloc.bh); |
|---|
| 483 | 516 | } |
|---|
| 484 | | - |
|---|
| 485 | | - err = dquot_initialize(inode); |
|---|
| 486 | | - if (err) |
|---|
| 487 | | - return err; |
|---|
| 488 | 517 | |
|---|
| 489 | 518 | handle = ext4_journal_start(inode, EXT4_HT_QUOTA, |
|---|
| 490 | 519 | EXT4_QUOTA_INIT_BLOCKS(sb) + |
|---|
| .. | .. |
|---|
| 546 | 575 | xflags |= FS_XFLAG_NOATIME; |
|---|
| 547 | 576 | if (iflags & EXT4_PROJINHERIT_FL) |
|---|
| 548 | 577 | xflags |= FS_XFLAG_PROJINHERIT; |
|---|
| 578 | + if (iflags & EXT4_DAX_FL) |
|---|
| 579 | + xflags |= FS_XFLAG_DAX; |
|---|
| 549 | 580 | return xflags; |
|---|
| 550 | 581 | } |
|---|
| 551 | 582 | |
|---|
| 552 | 583 | #define EXT4_SUPPORTED_FS_XFLAGS (FS_XFLAG_SYNC | FS_XFLAG_IMMUTABLE | \ |
|---|
| 553 | 584 | FS_XFLAG_APPEND | FS_XFLAG_NODUMP | \ |
|---|
| 554 | | - FS_XFLAG_NOATIME | FS_XFLAG_PROJINHERIT) |
|---|
| 585 | + FS_XFLAG_NOATIME | FS_XFLAG_PROJINHERIT | \ |
|---|
| 586 | + FS_XFLAG_DAX) |
|---|
| 555 | 587 | |
|---|
| 556 | 588 | /* Transfer xflags flags to internal */ |
|---|
| 557 | 589 | static inline unsigned long ext4_xflags_to_iflags(__u32 xflags) |
|---|
| .. | .. |
|---|
| 570 | 602 | iflags |= EXT4_NOATIME_FL; |
|---|
| 571 | 603 | if (xflags & FS_XFLAG_PROJINHERIT) |
|---|
| 572 | 604 | iflags |= EXT4_PROJINHERIT_FL; |
|---|
| 605 | + if (xflags & FS_XFLAG_DAX) |
|---|
| 606 | + iflags |= EXT4_DAX_FL; |
|---|
| 573 | 607 | |
|---|
| 574 | 608 | return iflags; |
|---|
| 575 | 609 | } |
|---|
| .. | .. |
|---|
| 578 | 612 | { |
|---|
| 579 | 613 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
|---|
| 580 | 614 | __u32 flags; |
|---|
| 615 | + int ret; |
|---|
| 581 | 616 | |
|---|
| 582 | 617 | if (!capable(CAP_SYS_ADMIN)) |
|---|
| 583 | 618 | return -EPERM; |
|---|
| .. | .. |
|---|
| 596 | 631 | |
|---|
| 597 | 632 | switch (flags) { |
|---|
| 598 | 633 | case EXT4_GOING_FLAGS_DEFAULT: |
|---|
| 599 | | - freeze_bdev(sb->s_bdev); |
|---|
| 634 | + ret = freeze_bdev(sb->s_bdev); |
|---|
| 635 | + if (ret) |
|---|
| 636 | + return ret; |
|---|
| 600 | 637 | set_bit(EXT4_FLAGS_SHUTDOWN, &sbi->s_ext4_flags); |
|---|
| 601 | | - thaw_bdev(sb->s_bdev, sb); |
|---|
| 638 | + thaw_bdev(sb->s_bdev); |
|---|
| 602 | 639 | break; |
|---|
| 603 | 640 | case EXT4_GOING_FLAGS_LOGFLUSH: |
|---|
| 604 | 641 | set_bit(EXT4_FLAGS_SHUTDOWN, &sbi->s_ext4_flags); |
|---|
| .. | .. |
|---|
| 645 | 682 | static int ext4_ioc_getfsmap(struct super_block *sb, |
|---|
| 646 | 683 | struct fsmap_head __user *arg) |
|---|
| 647 | 684 | { |
|---|
| 648 | | - struct getfsmap_info info = {0}; |
|---|
| 685 | + struct getfsmap_info info = { NULL }; |
|---|
| 649 | 686 | struct ext4_fsmap_head xhead = {0}; |
|---|
| 650 | 687 | struct fsmap_head head; |
|---|
| 651 | 688 | bool aborted = false; |
|---|
| .. | .. |
|---|
| 741 | 778 | return err; |
|---|
| 742 | 779 | } |
|---|
| 743 | 780 | |
|---|
| 744 | | -static int ext4_ioctl_check_project(struct inode *inode, struct fsxattr *fa) |
|---|
| 781 | +static void ext4_fill_fsxattr(struct inode *inode, struct fsxattr *fa) |
|---|
| 745 | 782 | { |
|---|
| 746 | | - /* |
|---|
| 747 | | - * Project Quota ID state is only allowed to change from within the init |
|---|
| 748 | | - * namespace. Enforce that restriction only if we are trying to change |
|---|
| 749 | | - * the quota ID state. Everything else is allowed in user namespaces. |
|---|
| 750 | | - */ |
|---|
| 751 | | - if (current_user_ns() == &init_user_ns) |
|---|
| 752 | | - return 0; |
|---|
| 783 | + struct ext4_inode_info *ei = EXT4_I(inode); |
|---|
| 753 | 784 | |
|---|
| 754 | | - if (__kprojid_val(EXT4_I(inode)->i_projid) != fa->fsx_projid) |
|---|
| 755 | | - return -EINVAL; |
|---|
| 785 | + simple_fill_fsxattr(fa, ext4_iflags_to_xflags(ei->i_flags & |
|---|
| 786 | + EXT4_FL_USER_VISIBLE)); |
|---|
| 756 | 787 | |
|---|
| 757 | | - if (ext4_test_inode_flag(inode, EXT4_INODE_PROJINHERIT)) { |
|---|
| 758 | | - if (!(fa->fsx_xflags & FS_XFLAG_PROJINHERIT)) |
|---|
| 759 | | - return -EINVAL; |
|---|
| 760 | | - } else { |
|---|
| 761 | | - if (fa->fsx_xflags & FS_XFLAG_PROJINHERIT) |
|---|
| 762 | | - return -EINVAL; |
|---|
| 763 | | - } |
|---|
| 764 | | - |
|---|
| 765 | | - return 0; |
|---|
| 788 | + if (ext4_has_feature_project(inode->i_sb)) |
|---|
| 789 | + fa->fsx_projid = from_kprojid(&init_user_ns, ei->i_projid); |
|---|
| 766 | 790 | } |
|---|
| 767 | 791 | |
|---|
| 768 | | -long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
|---|
| 792 | +/* So that the fiemap access checks can't overflow on 32 bit machines. */ |
|---|
| 793 | +#define FIEMAP_MAX_EXTENTS (UINT_MAX / sizeof(struct fiemap_extent)) |
|---|
| 794 | + |
|---|
| 795 | +static int ext4_ioctl_get_es_cache(struct file *filp, unsigned long arg) |
|---|
| 796 | +{ |
|---|
| 797 | + struct fiemap fiemap; |
|---|
| 798 | + struct fiemap __user *ufiemap = (struct fiemap __user *) arg; |
|---|
| 799 | + struct fiemap_extent_info fieinfo = { 0, }; |
|---|
| 800 | + struct inode *inode = file_inode(filp); |
|---|
| 801 | + int error; |
|---|
| 802 | + |
|---|
| 803 | + if (copy_from_user(&fiemap, ufiemap, sizeof(fiemap))) |
|---|
| 804 | + return -EFAULT; |
|---|
| 805 | + |
|---|
| 806 | + if (fiemap.fm_extent_count > FIEMAP_MAX_EXTENTS) |
|---|
| 807 | + return -EINVAL; |
|---|
| 808 | + |
|---|
| 809 | + fieinfo.fi_flags = fiemap.fm_flags; |
|---|
| 810 | + fieinfo.fi_extents_max = fiemap.fm_extent_count; |
|---|
| 811 | + fieinfo.fi_extents_start = ufiemap->fm_extents; |
|---|
| 812 | + |
|---|
| 813 | + error = ext4_get_es_cache(inode, &fieinfo, fiemap.fm_start, |
|---|
| 814 | + fiemap.fm_length); |
|---|
| 815 | + fiemap.fm_flags = fieinfo.fi_flags; |
|---|
| 816 | + fiemap.fm_mapped_extents = fieinfo.fi_extents_mapped; |
|---|
| 817 | + if (copy_to_user(ufiemap, &fiemap, sizeof(fiemap))) |
|---|
| 818 | + error = -EFAULT; |
|---|
| 819 | + |
|---|
| 820 | + return error; |
|---|
| 821 | +} |
|---|
| 822 | + |
|---|
| 823 | +static long __ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
|---|
| 769 | 824 | { |
|---|
| 770 | 825 | struct inode *inode = file_inode(filp); |
|---|
| 771 | 826 | struct super_block *sb = inode->i_sb; |
|---|
| .. | .. |
|---|
| 777 | 832 | switch (cmd) { |
|---|
| 778 | 833 | case FS_IOC_GETFSMAP: |
|---|
| 779 | 834 | return ext4_ioc_getfsmap(sb, (void __user *)arg); |
|---|
| 780 | | - case EXT4_IOC_GETFLAGS: |
|---|
| 835 | + case FS_IOC_GETFLAGS: |
|---|
| 781 | 836 | flags = ei->i_flags & EXT4_FL_USER_VISIBLE; |
|---|
| 837 | + if (S_ISREG(inode->i_mode)) |
|---|
| 838 | + flags &= ~EXT4_PROJINHERIT_FL; |
|---|
| 782 | 839 | return put_user(flags, (int __user *) arg); |
|---|
| 783 | | - case EXT4_IOC_SETFLAGS: { |
|---|
| 840 | + case FS_IOC_SETFLAGS: { |
|---|
| 784 | 841 | int err; |
|---|
| 785 | 842 | |
|---|
| 786 | 843 | if (!inode_owner_or_capable(inode)) |
|---|
| .. | .. |
|---|
| 1030 | 1087 | |
|---|
| 1031 | 1088 | err = ext4_resize_fs(sb, n_blocks_count); |
|---|
| 1032 | 1089 | if (EXT4_SB(sb)->s_journal) { |
|---|
| 1090 | + ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_RESIZE); |
|---|
| 1033 | 1091 | jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); |
|---|
| 1034 | 1092 | err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal); |
|---|
| 1035 | 1093 | jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); |
|---|
| .. | .. |
|---|
| 1083 | 1141 | case EXT4_IOC_PRECACHE_EXTENTS: |
|---|
| 1084 | 1142 | return ext4_ext_precache(inode); |
|---|
| 1085 | 1143 | |
|---|
| 1086 | | - case EXT4_IOC_SET_ENCRYPTION_POLICY: |
|---|
| 1144 | + case FS_IOC_SET_ENCRYPTION_POLICY: |
|---|
| 1087 | 1145 | if (!ext4_has_feature_encrypt(sb)) |
|---|
| 1088 | 1146 | return -EOPNOTSUPP; |
|---|
| 1089 | 1147 | return fscrypt_ioctl_set_policy(filp, (const void __user *)arg); |
|---|
| 1090 | 1148 | |
|---|
| 1091 | | - case EXT4_IOC_GET_ENCRYPTION_PWSALT: { |
|---|
| 1149 | + case FS_IOC_GET_ENCRYPTION_PWSALT: { |
|---|
| 1092 | 1150 | #ifdef CONFIG_FS_ENCRYPTION |
|---|
| 1093 | 1151 | int err, err2; |
|---|
| 1094 | 1152 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
|---|
| .. | .. |
|---|
| 1131 | 1189 | return -EOPNOTSUPP; |
|---|
| 1132 | 1190 | #endif |
|---|
| 1133 | 1191 | } |
|---|
| 1134 | | - case EXT4_IOC_GET_ENCRYPTION_POLICY: |
|---|
| 1192 | + case FS_IOC_GET_ENCRYPTION_POLICY: |
|---|
| 1135 | 1193 | if (!ext4_has_feature_encrypt(sb)) |
|---|
| 1136 | 1194 | return -EOPNOTSUPP; |
|---|
| 1137 | 1195 | return fscrypt_ioctl_get_policy(filp, (void __user *)arg); |
|---|
| .. | .. |
|---|
| 1166 | 1224 | return -EOPNOTSUPP; |
|---|
| 1167 | 1225 | return fscrypt_ioctl_get_nonce(filp, (void __user *)arg); |
|---|
| 1168 | 1226 | |
|---|
| 1169 | | - case EXT4_IOC_FSGETXATTR: |
|---|
| 1227 | + case EXT4_IOC_CLEAR_ES_CACHE: |
|---|
| 1228 | + { |
|---|
| 1229 | + if (!inode_owner_or_capable(inode)) |
|---|
| 1230 | + return -EACCES; |
|---|
| 1231 | + ext4_clear_inode_es(inode); |
|---|
| 1232 | + return 0; |
|---|
| 1233 | + } |
|---|
| 1234 | + |
|---|
| 1235 | + case EXT4_IOC_GETSTATE: |
|---|
| 1236 | + { |
|---|
| 1237 | + __u32 state = 0; |
|---|
| 1238 | + |
|---|
| 1239 | + if (ext4_test_inode_state(inode, EXT4_STATE_EXT_PRECACHED)) |
|---|
| 1240 | + state |= EXT4_STATE_FLAG_EXT_PRECACHED; |
|---|
| 1241 | + if (ext4_test_inode_state(inode, EXT4_STATE_NEW)) |
|---|
| 1242 | + state |= EXT4_STATE_FLAG_NEW; |
|---|
| 1243 | + if (ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY)) |
|---|
| 1244 | + state |= EXT4_STATE_FLAG_NEWENTRY; |
|---|
| 1245 | + if (ext4_test_inode_state(inode, EXT4_STATE_DA_ALLOC_CLOSE)) |
|---|
| 1246 | + state |= EXT4_STATE_FLAG_DA_ALLOC_CLOSE; |
|---|
| 1247 | + |
|---|
| 1248 | + return put_user(state, (__u32 __user *) arg); |
|---|
| 1249 | + } |
|---|
| 1250 | + |
|---|
| 1251 | + case EXT4_IOC_GET_ES_CACHE: |
|---|
| 1252 | + return ext4_ioctl_get_es_cache(filp, arg); |
|---|
| 1253 | + |
|---|
| 1254 | + case FS_IOC_FSGETXATTR: |
|---|
| 1170 | 1255 | { |
|---|
| 1171 | 1256 | struct fsxattr fa; |
|---|
| 1172 | 1257 | |
|---|
| 1173 | | - memset(&fa, 0, sizeof(struct fsxattr)); |
|---|
| 1174 | | - fa.fsx_xflags = ext4_iflags_to_xflags(ei->i_flags & EXT4_FL_USER_VISIBLE); |
|---|
| 1175 | | - |
|---|
| 1176 | | - if (ext4_has_feature_project(inode->i_sb)) { |
|---|
| 1177 | | - fa.fsx_projid = (__u32)from_kprojid(&init_user_ns, |
|---|
| 1178 | | - EXT4_I(inode)->i_projid); |
|---|
| 1179 | | - } |
|---|
| 1258 | + ext4_fill_fsxattr(inode, &fa); |
|---|
| 1180 | 1259 | |
|---|
| 1181 | 1260 | if (copy_to_user((struct fsxattr __user *)arg, |
|---|
| 1182 | 1261 | &fa, sizeof(fa))) |
|---|
| 1183 | 1262 | return -EFAULT; |
|---|
| 1184 | 1263 | return 0; |
|---|
| 1185 | 1264 | } |
|---|
| 1186 | | - case EXT4_IOC_FSSETXATTR: |
|---|
| 1265 | + case FS_IOC_FSSETXATTR: |
|---|
| 1187 | 1266 | { |
|---|
| 1188 | | - struct fsxattr fa; |
|---|
| 1267 | + struct fsxattr fa, old_fa; |
|---|
| 1189 | 1268 | int err; |
|---|
| 1190 | 1269 | |
|---|
| 1191 | 1270 | if (copy_from_user(&fa, (struct fsxattr __user *)arg, |
|---|
| .. | .. |
|---|
| 1208 | 1287 | return err; |
|---|
| 1209 | 1288 | |
|---|
| 1210 | 1289 | inode_lock(inode); |
|---|
| 1211 | | - err = ext4_ioctl_check_project(inode, &fa); |
|---|
| 1290 | + ext4_fill_fsxattr(inode, &old_fa); |
|---|
| 1291 | + err = vfs_ioc_fssetxattr_check(inode, &old_fa, &fa); |
|---|
| 1212 | 1292 | if (err) |
|---|
| 1213 | 1293 | goto out; |
|---|
| 1214 | 1294 | flags = (ei->i_flags & ~EXT4_FL_XFLAG_VISIBLE) | |
|---|
| .. | .. |
|---|
| 1238 | 1318 | return -EOPNOTSUPP; |
|---|
| 1239 | 1319 | return fsverity_ioctl_measure(filp, (void __user *)arg); |
|---|
| 1240 | 1320 | |
|---|
| 1321 | + case FS_IOC_READ_VERITY_METADATA: |
|---|
| 1322 | + if (!ext4_has_feature_verity(sb)) |
|---|
| 1323 | + return -EOPNOTSUPP; |
|---|
| 1324 | + return fsverity_ioctl_read_metadata(filp, |
|---|
| 1325 | + (const void __user *)arg); |
|---|
| 1326 | + |
|---|
| 1241 | 1327 | default: |
|---|
| 1242 | 1328 | return -ENOTTY; |
|---|
| 1243 | 1329 | } |
|---|
| 1330 | +} |
|---|
| 1331 | + |
|---|
| 1332 | +long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
|---|
| 1333 | +{ |
|---|
| 1334 | + return __ext4_ioctl(filp, cmd, arg); |
|---|
| 1244 | 1335 | } |
|---|
| 1245 | 1336 | |
|---|
| 1246 | 1337 | #ifdef CONFIG_COMPAT |
|---|
| .. | .. |
|---|
| 1248 | 1339 | { |
|---|
| 1249 | 1340 | /* These are just misnamed, they actually get/put from/to user an int */ |
|---|
| 1250 | 1341 | switch (cmd) { |
|---|
| 1251 | | - case EXT4_IOC32_GETFLAGS: |
|---|
| 1252 | | - cmd = EXT4_IOC_GETFLAGS; |
|---|
| 1342 | + case FS_IOC32_GETFLAGS: |
|---|
| 1343 | + cmd = FS_IOC_GETFLAGS; |
|---|
| 1253 | 1344 | break; |
|---|
| 1254 | | - case EXT4_IOC32_SETFLAGS: |
|---|
| 1255 | | - cmd = EXT4_IOC_SETFLAGS; |
|---|
| 1345 | + case FS_IOC32_SETFLAGS: |
|---|
| 1346 | + cmd = FS_IOC_SETFLAGS; |
|---|
| 1256 | 1347 | break; |
|---|
| 1257 | 1348 | case EXT4_IOC32_GETVERSION: |
|---|
| 1258 | 1349 | cmd = EXT4_IOC_GETVERSION; |
|---|
| .. | .. |
|---|
| 1294 | 1385 | } |
|---|
| 1295 | 1386 | case EXT4_IOC_MOVE_EXT: |
|---|
| 1296 | 1387 | case EXT4_IOC_RESIZE_FS: |
|---|
| 1388 | + case FITRIM: |
|---|
| 1297 | 1389 | case EXT4_IOC_PRECACHE_EXTENTS: |
|---|
| 1298 | | - case EXT4_IOC_SET_ENCRYPTION_POLICY: |
|---|
| 1299 | | - case EXT4_IOC_GET_ENCRYPTION_PWSALT: |
|---|
| 1300 | | - case EXT4_IOC_GET_ENCRYPTION_POLICY: |
|---|
| 1390 | + case FS_IOC_SET_ENCRYPTION_POLICY: |
|---|
| 1391 | + case FS_IOC_GET_ENCRYPTION_PWSALT: |
|---|
| 1392 | + case FS_IOC_GET_ENCRYPTION_POLICY: |
|---|
| 1301 | 1393 | case FS_IOC_GET_ENCRYPTION_POLICY_EX: |
|---|
| 1302 | 1394 | case FS_IOC_ADD_ENCRYPTION_KEY: |
|---|
| 1303 | 1395 | case FS_IOC_REMOVE_ENCRYPTION_KEY: |
|---|
| .. | .. |
|---|
| 1308 | 1400 | case FS_IOC_GETFSMAP: |
|---|
| 1309 | 1401 | case FS_IOC_ENABLE_VERITY: |
|---|
| 1310 | 1402 | case FS_IOC_MEASURE_VERITY: |
|---|
| 1311 | | - case EXT4_IOC_FSGETXATTR: |
|---|
| 1312 | | - case EXT4_IOC_FSSETXATTR: |
|---|
| 1403 | + case FS_IOC_READ_VERITY_METADATA: |
|---|
| 1404 | + case EXT4_IOC_CLEAR_ES_CACHE: |
|---|
| 1405 | + case EXT4_IOC_GETSTATE: |
|---|
| 1406 | + case EXT4_IOC_GET_ES_CACHE: |
|---|
| 1407 | + case FS_IOC_FSGETXATTR: |
|---|
| 1408 | + case FS_IOC_FSSETXATTR: |
|---|
| 1313 | 1409 | break; |
|---|
| 1314 | 1410 | default: |
|---|
| 1315 | 1411 | return -ENOIOCTLCMD; |
|---|