LCOV - code coverage report
Current view: top level - fs/ext4 - ioctl.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 9 734 1.2 %
Date: 2022-03-28 13:20:08 Functions: 1 16 6.2 %
Branches: 2 489 0.4 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0
       2                 :            : /*
       3                 :            :  * linux/fs/ext4/ioctl.c
       4                 :            :  *
       5                 :            :  * Copyright (C) 1993, 1994, 1995
       6                 :            :  * Remy Card (card@masi.ibp.fr)
       7                 :            :  * Laboratoire MASI - Institut Blaise Pascal
       8                 :            :  * Universite Pierre et Marie Curie (Paris VI)
       9                 :            :  */
      10                 :            : 
      11                 :            : #include <linux/fs.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 <linux/quotaops.h>
      18                 :            : #include <linux/random.h>
      19                 :            : #include <linux/uuid.h>
      20                 :            : #include <linux/uaccess.h>
      21                 :            : #include <linux/delay.h>
      22                 :            : #include <linux/iversion.h>
      23                 :            : #include "ext4_jbd2.h"
      24                 :            : #include "ext4.h"
      25                 :            : #include <linux/fsmap.h>
      26                 :            : #include "fsmap.h"
      27                 :            : #include <trace/events/ext4.h>
      28                 :            : 
      29                 :            : /**
      30                 :            :  * Swap memory between @a and @b for @len bytes.
      31                 :            :  *
      32                 :            :  * @a:          pointer to first memory area
      33                 :            :  * @b:          pointer to second memory area
      34                 :            :  * @len:        number of bytes to swap
      35                 :            :  *
      36                 :            :  */
      37                 :          0 : static void memswap(void *a, void *b, size_t len)
      38                 :            : {
      39                 :          0 :         unsigned char *ap, *bp;
      40                 :            : 
      41                 :          0 :         ap = (unsigned char *)a;
      42                 :          0 :         bp = (unsigned char *)b;
      43         [ #  # ]:          0 :         while (len-- > 0) {
      44                 :          0 :                 swap(*ap, *bp);
      45                 :          0 :                 ap++;
      46                 :          0 :                 bp++;
      47                 :            :         }
      48                 :            : }
      49                 :            : 
      50                 :            : /**
      51                 :            :  * Swap i_data and associated attributes between @inode1 and @inode2.
      52                 :            :  * This function is used for the primary swap between inode1 and inode2
      53                 :            :  * and also to revert this primary swap in case of errors.
      54                 :            :  *
      55                 :            :  * Therefore you have to make sure, that calling this method twice
      56                 :            :  * will revert all changes.
      57                 :            :  *
      58                 :            :  * @inode1:     pointer to first inode
      59                 :            :  * @inode2:     pointer to second inode
      60                 :            :  */
      61                 :          0 : static void swap_inode_data(struct inode *inode1, struct inode *inode2)
      62                 :            : {
      63                 :          0 :         loff_t isize;
      64                 :          0 :         struct ext4_inode_info *ei1;
      65                 :          0 :         struct ext4_inode_info *ei2;
      66                 :          0 :         unsigned long tmp;
      67                 :            : 
      68                 :          0 :         ei1 = EXT4_I(inode1);
      69                 :          0 :         ei2 = EXT4_I(inode2);
      70                 :            : 
      71                 :          0 :         swap(inode1->i_version, inode2->i_version);
      72                 :          0 :         swap(inode1->i_atime, inode2->i_atime);
      73                 :          0 :         swap(inode1->i_mtime, inode2->i_mtime);
      74                 :            : 
      75                 :          0 :         memswap(ei1->i_data, ei2->i_data, sizeof(ei1->i_data));
      76                 :          0 :         tmp = ei1->i_flags & EXT4_FL_SHOULD_SWAP;
      77                 :          0 :         ei1->i_flags = (ei2->i_flags & EXT4_FL_SHOULD_SWAP) |
      78                 :          0 :                 (ei1->i_flags & ~EXT4_FL_SHOULD_SWAP);
      79                 :          0 :         ei2->i_flags = tmp | (ei2->i_flags & ~EXT4_FL_SHOULD_SWAP);
      80                 :          0 :         swap(ei1->i_disksize, ei2->i_disksize);
      81                 :          0 :         ext4_es_remove_extent(inode1, 0, EXT_MAX_BLOCKS);
      82                 :          0 :         ext4_es_remove_extent(inode2, 0, EXT_MAX_BLOCKS);
      83                 :            : 
      84                 :          0 :         isize = i_size_read(inode1);
      85                 :          0 :         i_size_write(inode1, i_size_read(inode2));
      86                 :          0 :         i_size_write(inode2, isize);
      87                 :          0 : }
      88                 :            : 
      89                 :          0 : static void reset_inode_seed(struct inode *inode)
      90                 :            : {
      91                 :          0 :         struct ext4_inode_info *ei = EXT4_I(inode);
      92                 :          0 :         struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
      93                 :          0 :         __le32 inum = cpu_to_le32(inode->i_ino);
      94                 :          0 :         __le32 gen = cpu_to_le32(inode->i_generation);
      95                 :          0 :         __u32 csum;
      96                 :            : 
      97         [ #  # ]:          0 :         if (!ext4_has_metadata_csum(inode->i_sb))
      98                 :          0 :                 return;
      99                 :            : 
     100                 :          0 :         csum = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)&inum, sizeof(inum));
     101                 :          0 :         ei->i_csum_seed = ext4_chksum(sbi, csum, (__u8 *)&gen, sizeof(gen));
     102                 :            : }
     103                 :            : 
     104                 :            : /**
     105                 :            :  * Swap the information from the given @inode and the inode
     106                 :            :  * EXT4_BOOT_LOADER_INO. It will basically swap i_data and all other
     107                 :            :  * important fields of the inodes.
     108                 :            :  *
     109                 :            :  * @sb:         the super block of the filesystem
     110                 :            :  * @inode:      the inode to swap with EXT4_BOOT_LOADER_INO
     111                 :            :  *
     112                 :            :  */
     113                 :          0 : static long swap_inode_boot_loader(struct super_block *sb,
     114                 :            :                                 struct inode *inode)
     115                 :            : {
     116                 :          0 :         handle_t *handle;
     117                 :          0 :         int err;
     118                 :          0 :         struct inode *inode_bl;
     119                 :          0 :         struct ext4_inode_info *ei_bl;
     120                 :          0 :         qsize_t size, size_bl, diff;
     121                 :          0 :         blkcnt_t blocks;
     122                 :          0 :         unsigned short bytes;
     123                 :            : 
     124                 :          0 :         inode_bl = ext4_iget(sb, EXT4_BOOT_LOADER_INO, EXT4_IGET_SPECIAL);
     125         [ #  # ]:          0 :         if (IS_ERR(inode_bl))
     126                 :          0 :                 return PTR_ERR(inode_bl);
     127                 :          0 :         ei_bl = EXT4_I(inode_bl);
     128                 :            : 
     129                 :            :         /* Protect orig inodes against a truncate and make sure,
     130                 :            :          * that only 1 swap_inode_boot_loader is running. */
     131                 :          0 :         lock_two_nondirectories(inode, inode_bl);
     132                 :            : 
     133   [ #  #  #  # ]:          0 :         if (inode->i_nlink != 1 || !S_ISREG(inode->i_mode) ||
     134         [ #  # ]:          0 :             IS_SWAPFILE(inode) || IS_ENCRYPTED(inode) ||
     135         [ #  # ]:          0 :             (EXT4_I(inode)->i_flags & EXT4_JOURNAL_DATA_FL) ||
     136                 :            :             ext4_has_inline_data(inode)) {
     137                 :          0 :                 err = -EINVAL;
     138                 :          0 :                 goto journal_err_out;
     139                 :            :         }
     140                 :            : 
     141   [ #  #  #  #  :          0 :         if (IS_RDONLY(inode) || IS_APPEND(inode) || IS_IMMUTABLE(inode) ||
                   #  # ]
     142         [ #  # ]:          0 :             !inode_owner_or_capable(inode) || !capable(CAP_SYS_ADMIN)) {
     143                 :          0 :                 err = -EPERM;
     144                 :          0 :                 goto journal_err_out;
     145                 :            :         }
     146                 :            : 
     147                 :          0 :         down_write(&EXT4_I(inode)->i_mmap_sem);
     148                 :          0 :         err = filemap_write_and_wait(inode->i_mapping);
     149         [ #  # ]:          0 :         if (err)
     150                 :          0 :                 goto err_out;
     151                 :            : 
     152                 :          0 :         err = filemap_write_and_wait(inode_bl->i_mapping);
     153         [ #  # ]:          0 :         if (err)
     154                 :          0 :                 goto err_out;
     155                 :            : 
     156                 :            :         /* Wait for all existing dio workers */
     157                 :          0 :         inode_dio_wait(inode);
     158                 :          0 :         inode_dio_wait(inode_bl);
     159                 :            : 
     160                 :          0 :         truncate_inode_pages(&inode->i_data, 0);
     161                 :          0 :         truncate_inode_pages(&inode_bl->i_data, 0);
     162                 :            : 
     163                 :          0 :         handle = ext4_journal_start(inode_bl, EXT4_HT_MOVE_EXTENTS, 2);
     164         [ #  # ]:          0 :         if (IS_ERR(handle)) {
     165                 :          0 :                 err = -EINVAL;
     166                 :          0 :                 goto err_out;
     167                 :            :         }
     168                 :            : 
     169                 :            :         /* Protect extent tree against block allocations via delalloc */
     170                 :          0 :         ext4_double_down_write_data_sem(inode, inode_bl);
     171                 :            : 
     172         [ #  # ]:          0 :         if (inode_bl->i_nlink == 0) {
     173                 :            :                 /* this inode has never been used as a BOOT_LOADER */
     174                 :          0 :                 set_nlink(inode_bl, 1);
     175                 :          0 :                 i_uid_write(inode_bl, 0);
     176                 :          0 :                 i_gid_write(inode_bl, 0);
     177                 :          0 :                 inode_bl->i_flags = 0;
     178                 :          0 :                 ei_bl->i_flags = 0;
     179                 :          0 :                 inode_set_iversion(inode_bl, 1);
     180         [ #  # ]:          0 :                 i_size_write(inode_bl, 0);
     181                 :          0 :                 inode_bl->i_mode = S_IFREG;
     182         [ #  # ]:          0 :                 if (ext4_has_feature_extents(sb)) {
     183                 :          0 :                         ext4_set_inode_flag(inode_bl, EXT4_INODE_EXTENTS);
     184                 :          0 :                         ext4_ext_tree_init(handle, inode_bl);
     185                 :            :                 } else
     186                 :          0 :                         memset(ei_bl->i_data, 0, sizeof(ei_bl->i_data));
     187                 :            :         }
     188                 :            : 
     189                 :          0 :         err = dquot_initialize(inode);
     190         [ #  # ]:          0 :         if (err)
     191                 :          0 :                 goto err_out1;
     192                 :            : 
     193                 :          0 :         size = (qsize_t)(inode->i_blocks) * (1 << 9) + inode->i_bytes;
     194                 :          0 :         size_bl = (qsize_t)(inode_bl->i_blocks) * (1 << 9) + inode_bl->i_bytes;
     195                 :          0 :         diff = size - size_bl;
     196                 :          0 :         swap_inode_data(inode, inode_bl);
     197                 :            : 
     198                 :          0 :         inode->i_ctime = inode_bl->i_ctime = current_time(inode);
     199                 :            : 
     200                 :          0 :         inode->i_generation = prandom_u32();
     201                 :          0 :         inode_bl->i_generation = prandom_u32();
     202                 :          0 :         reset_inode_seed(inode);
     203                 :          0 :         reset_inode_seed(inode_bl);
     204                 :            : 
     205                 :          0 :         ext4_discard_preallocations(inode);
     206                 :            : 
     207                 :          0 :         err = ext4_mark_inode_dirty(handle, inode);
     208         [ #  # ]:          0 :         if (err < 0) {
     209                 :            :                 /* No need to update quota information. */
     210                 :          0 :                 ext4_warning(inode->i_sb,
     211                 :            :                         "couldn't mark inode #%lu dirty (err %d)",
     212                 :            :                         inode->i_ino, err);
     213                 :            :                 /* Revert all changes: */
     214                 :          0 :                 swap_inode_data(inode, inode_bl);
     215                 :          0 :                 ext4_mark_inode_dirty(handle, inode);
     216                 :          0 :                 goto err_out1;
     217                 :            :         }
     218                 :            : 
     219                 :          0 :         blocks = inode_bl->i_blocks;
     220                 :          0 :         bytes = inode_bl->i_bytes;
     221                 :          0 :         inode_bl->i_blocks = inode->i_blocks;
     222                 :          0 :         inode_bl->i_bytes = inode->i_bytes;
     223                 :          0 :         err = ext4_mark_inode_dirty(handle, inode_bl);
     224         [ #  # ]:          0 :         if (err < 0) {
     225                 :            :                 /* No need to update quota information. */
     226                 :          0 :                 ext4_warning(inode_bl->i_sb,
     227                 :            :                         "couldn't mark inode #%lu dirty (err %d)",
     228                 :            :                         inode_bl->i_ino, err);
     229                 :          0 :                 goto revert;
     230                 :            :         }
     231                 :            : 
     232                 :            :         /* Bootloader inode should not be counted into quota information. */
     233         [ #  # ]:          0 :         if (diff > 0)
     234                 :          0 :                 dquot_free_space(inode, diff);
     235                 :            :         else
     236                 :          0 :                 err = dquot_alloc_space(inode, -1 * diff);
     237                 :            : 
     238         [ #  # ]:          0 :         if (err < 0) {
     239                 :          0 : revert:
     240                 :            :                 /* Revert all changes: */
     241                 :          0 :                 inode_bl->i_blocks = blocks;
     242                 :          0 :                 inode_bl->i_bytes = bytes;
     243                 :          0 :                 swap_inode_data(inode, inode_bl);
     244                 :          0 :                 ext4_mark_inode_dirty(handle, inode);
     245                 :          0 :                 ext4_mark_inode_dirty(handle, inode_bl);
     246                 :            :         }
     247                 :            : 
     248                 :          0 : err_out1:
     249                 :          0 :         ext4_journal_stop(handle);
     250                 :          0 :         ext4_double_up_write_data_sem(inode, inode_bl);
     251                 :            : 
     252                 :          0 : err_out:
     253                 :          0 :         up_write(&EXT4_I(inode)->i_mmap_sem);
     254                 :          0 : journal_err_out:
     255                 :          0 :         unlock_two_nondirectories(inode, inode_bl);
     256                 :          0 :         iput(inode_bl);
     257                 :          0 :         return err;
     258                 :            : }
     259                 :            : 
     260                 :            : #ifdef CONFIG_FS_ENCRYPTION
     261                 :            : static int uuid_is_zero(__u8 u[16])
     262                 :            : {
     263                 :            :         int     i;
     264                 :            : 
     265                 :            :         for (i = 0; i < 16; i++)
     266                 :            :                 if (u[i])
     267                 :            :                         return 0;
     268                 :            :         return 1;
     269                 :            : }
     270                 :            : #endif
     271                 :            : 
     272                 :            : /*
     273                 :            :  * If immutable is set and we are not clearing it, we're not allowed to change
     274                 :            :  * anything else in the inode.  Don't error out if we're only trying to set
     275                 :            :  * immutable on an immutable file.
     276                 :            :  */
     277                 :          0 : static int ext4_ioctl_check_immutable(struct inode *inode, __u32 new_projid,
     278                 :            :                                       unsigned int flags)
     279                 :            : {
     280                 :          0 :         struct ext4_inode_info *ei = EXT4_I(inode);
     281                 :          0 :         unsigned int oldflags = ei->i_flags;
     282                 :            : 
     283   [ #  #  #  # ]:          0 :         if (!(oldflags & EXT4_IMMUTABLE_FL) || !(flags & EXT4_IMMUTABLE_FL))
     284                 :            :                 return 0;
     285                 :            : 
     286         [ #  # ]:          0 :         if ((oldflags & ~EXT4_IMMUTABLE_FL) != (flags & ~EXT4_IMMUTABLE_FL))
     287                 :            :                 return -EPERM;
     288   [ #  #  #  # ]:          0 :         if (ext4_has_feature_project(inode->i_sb) &&
     289                 :            :             __kprojid_val(ei->i_projid) != new_projid)
     290                 :          0 :                 return -EPERM;
     291                 :            : 
     292                 :            :         return 0;
     293                 :            : }
     294                 :            : 
     295                 :          0 : static int ext4_ioctl_setflags(struct inode *inode,
     296                 :            :                                unsigned int flags)
     297                 :            : {
     298                 :          0 :         struct ext4_inode_info *ei = EXT4_I(inode);
     299                 :          0 :         handle_t *handle = NULL;
     300                 :          0 :         int err = -EPERM, migrate = 0;
     301                 :          0 :         struct ext4_iloc iloc;
     302                 :          0 :         unsigned int oldflags, mask, i;
     303                 :          0 :         unsigned int jflag;
     304                 :          0 :         struct super_block *sb = inode->i_sb;
     305                 :            : 
     306                 :            :         /* Is it quota file? Do not allow user to mess with it */
     307   [ #  #  #  # ]:          0 :         if (ext4_is_quota_file(inode))
     308                 :          0 :                 goto flags_out;
     309                 :            : 
     310                 :          0 :         oldflags = ei->i_flags;
     311                 :            : 
     312                 :            :         /* The JOURNAL_DATA flag is modifiable only by root */
     313                 :          0 :         jflag = flags & EXT4_JOURNAL_DATA_FL;
     314                 :            : 
     315                 :          0 :         err = vfs_ioc_setflags_prepare(inode, oldflags, flags);
     316         [ #  # ]:          0 :         if (err)
     317                 :          0 :                 goto flags_out;
     318                 :            : 
     319                 :            :         /*
     320                 :            :          * The JOURNAL_DATA flag can only be changed by
     321                 :            :          * the relevant capability.
     322                 :            :          */
     323         [ #  # ]:          0 :         if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) {
     324         [ #  # ]:          0 :                 if (!capable(CAP_SYS_RESOURCE))
     325                 :          0 :                         goto flags_out;
     326                 :            :         }
     327         [ #  # ]:          0 :         if ((flags ^ oldflags) & EXT4_EXTENTS_FL)
     328                 :          0 :                 migrate = 1;
     329                 :            : 
     330         [ #  # ]:          0 :         if (flags & EXT4_EOFBLOCKS_FL) {
     331                 :            :                 /* we don't support adding EOFBLOCKS flag */
     332         [ #  # ]:          0 :                 if (!(oldflags & EXT4_EOFBLOCKS_FL)) {
     333                 :          0 :                         err = -EOPNOTSUPP;
     334                 :          0 :                         goto flags_out;
     335                 :            :                 }
     336         [ #  # ]:          0 :         } else if (oldflags & EXT4_EOFBLOCKS_FL) {
     337                 :          0 :                 err = ext4_truncate(inode);
     338         [ #  # ]:          0 :                 if (err)
     339                 :          0 :                         goto flags_out;
     340                 :            :         }
     341                 :            : 
     342         [ #  # ]:          0 :         if ((flags ^ oldflags) & EXT4_CASEFOLD_FL) {
     343         [ #  # ]:          0 :                 if (!ext4_has_feature_casefold(sb)) {
     344                 :          0 :                         err = -EOPNOTSUPP;
     345                 :          0 :                         goto flags_out;
     346                 :            :                 }
     347                 :            : 
     348         [ #  # ]:          0 :                 if (!S_ISDIR(inode->i_mode)) {
     349                 :          0 :                         err = -ENOTDIR;
     350                 :          0 :                         goto flags_out;
     351                 :            :                 }
     352                 :            : 
     353         [ #  # ]:          0 :                 if (!ext4_empty_dir(inode)) {
     354                 :          0 :                         err = -ENOTEMPTY;
     355                 :          0 :                         goto flags_out;
     356                 :            :                 }
     357                 :            :         }
     358                 :            : 
     359                 :            :         /*
     360                 :            :          * Wait for all pending directio and then flush all the dirty pages
     361                 :            :          * for this file.  The flush marks all the pages readonly, so any
     362                 :            :          * subsequent attempt to write to the file (particularly mmap pages)
     363                 :            :          * will come through the filesystem and fail.
     364                 :            :          */
     365   [ #  #  #  # ]:          0 :         if (S_ISREG(inode->i_mode) && !IS_IMMUTABLE(inode) &&
     366         [ #  # ]:          0 :             (flags & EXT4_IMMUTABLE_FL)) {
     367                 :          0 :                 inode_dio_wait(inode);
     368                 :          0 :                 err = filemap_write_and_wait(inode->i_mapping);
     369         [ #  # ]:          0 :                 if (err)
     370                 :          0 :                         goto flags_out;
     371                 :            :         }
     372                 :            : 
     373                 :          0 :         handle = ext4_journal_start(inode, EXT4_HT_INODE, 1);
     374         [ #  # ]:          0 :         if (IS_ERR(handle)) {
     375                 :          0 :                 err = PTR_ERR(handle);
     376                 :          0 :                 goto flags_out;
     377                 :            :         }
     378   [ #  #  #  # ]:          0 :         if (IS_SYNC(inode))
     379         [ #  # ]:          0 :                 ext4_handle_sync(handle);
     380                 :          0 :         err = ext4_reserve_inode_write(handle, inode, &iloc);
     381         [ #  # ]:          0 :         if (err)
     382                 :          0 :                 goto flags_err;
     383                 :            : 
     384         [ #  # ]:          0 :         for (i = 0, mask = 1; i < 32; i++, mask <<= 1) {
     385         [ #  # ]:          0 :                 if (!(mask & EXT4_FL_USER_MODIFIABLE))
     386                 :          0 :                         continue;
     387                 :            :                 /* These flags get special treatment later */
     388         [ #  # ]:          0 :                 if (mask == EXT4_JOURNAL_DATA_FL || mask == EXT4_EXTENTS_FL)
     389                 :          0 :                         continue;
     390         [ #  # ]:          0 :                 if (mask & flags)
     391                 :          0 :                         ext4_set_inode_flag(inode, i);
     392                 :            :                 else
     393                 :          0 :                         ext4_clear_inode_flag(inode, i);
     394                 :            :         }
     395                 :            : 
     396                 :          0 :         ext4_set_inode_flags(inode);
     397                 :          0 :         inode->i_ctime = current_time(inode);
     398                 :            : 
     399                 :          0 :         err = ext4_mark_iloc_dirty(handle, inode, &iloc);
     400                 :          0 : flags_err:
     401                 :          0 :         ext4_journal_stop(handle);
     402         [ #  # ]:          0 :         if (err)
     403                 :          0 :                 goto flags_out;
     404                 :            : 
     405         [ #  # ]:          0 :         if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) {
     406                 :            :                 /*
     407                 :            :                  * Changes to the journaling mode can cause unsafe changes to
     408                 :            :                  * S_DAX if we are using the DAX mount option.
     409                 :            :                  */
     410                 :          0 :                 if (test_opt(inode->i_sb, DAX)) {
     411                 :            :                         err = -EBUSY;
     412                 :            :                         goto flags_out;
     413                 :            :                 }
     414                 :            : 
     415                 :          0 :                 err = ext4_change_inode_journal_flag(inode, jflag);
     416         [ #  # ]:          0 :                 if (err)
     417                 :          0 :                         goto flags_out;
     418                 :            :         }
     419         [ #  # ]:          0 :         if (migrate) {
     420         [ #  # ]:          0 :                 if (flags & EXT4_EXTENTS_FL)
     421                 :          0 :                         err = ext4_ext_migrate(inode);
     422                 :            :                 else
     423                 :          0 :                         err = ext4_ind_migrate(inode);
     424                 :            :         }
     425                 :            : 
     426                 :          0 : flags_out:
     427                 :          0 :         return err;
     428                 :            : }
     429                 :            : 
     430                 :            : #ifdef CONFIG_QUOTA
     431                 :          0 : static int ext4_ioctl_setproject(struct file *filp, __u32 projid)
     432                 :            : {
     433         [ #  # ]:          0 :         struct inode *inode = file_inode(filp);
     434                 :          0 :         struct super_block *sb = inode->i_sb;
     435                 :          0 :         struct ext4_inode_info *ei = EXT4_I(inode);
     436                 :          0 :         int err, rc;
     437                 :          0 :         handle_t *handle;
     438                 :          0 :         kprojid_t kprojid;
     439                 :          0 :         struct ext4_iloc iloc;
     440                 :          0 :         struct ext4_inode *raw_inode;
     441                 :          0 :         struct dquot *transfer_to[MAXQUOTAS] = { };
     442                 :            : 
     443         [ #  # ]:          0 :         if (!ext4_has_feature_project(sb)) {
     444         [ #  # ]:          0 :                 if (projid != EXT4_DEF_PROJID)
     445                 :            :                         return -EOPNOTSUPP;
     446                 :            :                 else
     447                 :          0 :                         return 0;
     448                 :            :         }
     449                 :            : 
     450         [ #  # ]:          0 :         if (EXT4_INODE_SIZE(sb) <= EXT4_GOOD_OLD_INODE_SIZE)
     451                 :            :                 return -EOPNOTSUPP;
     452                 :            : 
     453         [ #  # ]:          0 :         kprojid = make_kprojid(&init_user_ns, (projid_t)projid);
     454                 :            : 
     455         [ #  # ]:          0 :         if (projid_eq(kprojid, EXT4_I(inode)->i_projid))
     456                 :            :                 return 0;
     457                 :            : 
     458                 :          0 :         err = -EPERM;
     459                 :            :         /* Is it quota file? Do not allow user to mess with it */
     460   [ #  #  #  # ]:          0 :         if (ext4_is_quota_file(inode))
     461                 :            :                 return err;
     462                 :            : 
     463                 :          0 :         err = ext4_get_inode_loc(inode, &iloc);
     464         [ #  # ]:          0 :         if (err)
     465                 :            :                 return err;
     466                 :            : 
     467         [ #  # ]:          0 :         raw_inode = ext4_raw_inode(&iloc);
     468         [ #  # ]:          0 :         if (!EXT4_FITS_IN_INODE(raw_inode, ei, i_projid)) {
     469                 :          0 :                 err = ext4_expand_extra_isize(inode,
     470                 :          0 :                                               EXT4_SB(sb)->s_want_extra_isize,
     471                 :            :                                               &iloc);
     472         [ #  # ]:          0 :                 if (err)
     473                 :            :                         return err;
     474                 :            :         } else {
     475         [ #  # ]:          0 :                 brelse(iloc.bh);
     476                 :            :         }
     477                 :            : 
     478                 :          0 :         err = dquot_initialize(inode);
     479         [ #  # ]:          0 :         if (err)
     480                 :            :                 return err;
     481                 :            : 
     482   [ #  #  #  #  :          0 :         handle = ext4_journal_start(inode, EXT4_HT_QUOTA,
          #  #  #  #  #  
                      # ]
     483                 :            :                 EXT4_QUOTA_INIT_BLOCKS(sb) +
     484                 :            :                 EXT4_QUOTA_DEL_BLOCKS(sb) + 3);
     485         [ #  # ]:          0 :         if (IS_ERR(handle))
     486                 :          0 :                 return PTR_ERR(handle);
     487                 :            : 
     488                 :          0 :         err = ext4_reserve_inode_write(handle, inode, &iloc);
     489         [ #  # ]:          0 :         if (err)
     490                 :          0 :                 goto out_stop;
     491                 :            : 
     492                 :          0 :         transfer_to[PRJQUOTA] = dqget(sb, make_kqid_projid(kprojid));
     493         [ #  # ]:          0 :         if (!IS_ERR(transfer_to[PRJQUOTA])) {
     494                 :            : 
     495                 :            :                 /* __dquot_transfer() calls back ext4_get_inode_usage() which
     496                 :            :                  * counts xattr inode references.
     497                 :            :                  */
     498                 :          0 :                 down_read(&EXT4_I(inode)->xattr_sem);
     499                 :          0 :                 err = __dquot_transfer(inode, transfer_to);
     500                 :          0 :                 up_read(&EXT4_I(inode)->xattr_sem);
     501                 :          0 :                 dqput(transfer_to[PRJQUOTA]);
     502         [ #  # ]:          0 :                 if (err)
     503                 :          0 :                         goto out_dirty;
     504                 :            :         }
     505                 :            : 
     506                 :          0 :         EXT4_I(inode)->i_projid = kprojid;
     507                 :          0 :         inode->i_ctime = current_time(inode);
     508                 :          0 : out_dirty:
     509                 :          0 :         rc = ext4_mark_iloc_dirty(handle, inode, &iloc);
     510         [ #  # ]:          0 :         if (!err)
     511                 :          0 :                 err = rc;
     512                 :          0 : out_stop:
     513                 :          0 :         ext4_journal_stop(handle);
     514                 :          0 :         return err;
     515                 :            : }
     516                 :            : #else
     517                 :            : static int ext4_ioctl_setproject(struct file *filp, __u32 projid)
     518                 :            : {
     519                 :            :         if (projid != EXT4_DEF_PROJID)
     520                 :            :                 return -EOPNOTSUPP;
     521                 :            :         return 0;
     522                 :            : }
     523                 :            : #endif
     524                 :            : 
     525                 :            : /* Transfer internal flags to xflags */
     526                 :          0 : static inline __u32 ext4_iflags_to_xflags(unsigned long iflags)
     527                 :            : {
     528                 :          0 :         __u32 xflags = 0;
     529                 :            : 
     530         [ #  # ]:          0 :         if (iflags & EXT4_SYNC_FL)
     531                 :          0 :                 xflags |= FS_XFLAG_SYNC;
     532         [ #  # ]:          0 :         if (iflags & EXT4_IMMUTABLE_FL)
     533                 :          0 :                 xflags |= FS_XFLAG_IMMUTABLE;
     534         [ #  # ]:          0 :         if (iflags & EXT4_APPEND_FL)
     535                 :          0 :                 xflags |= FS_XFLAG_APPEND;
     536         [ #  # ]:          0 :         if (iflags & EXT4_NODUMP_FL)
     537                 :          0 :                 xflags |= FS_XFLAG_NODUMP;
     538         [ #  # ]:          0 :         if (iflags & EXT4_NOATIME_FL)
     539                 :          0 :                 xflags |= FS_XFLAG_NOATIME;
     540         [ #  # ]:          0 :         if (iflags & EXT4_PROJINHERIT_FL)
     541                 :          0 :                 xflags |= FS_XFLAG_PROJINHERIT;
     542                 :          0 :         return xflags;
     543                 :            : }
     544                 :            : 
     545                 :            : #define EXT4_SUPPORTED_FS_XFLAGS (FS_XFLAG_SYNC | FS_XFLAG_IMMUTABLE | \
     546                 :            :                                   FS_XFLAG_APPEND | FS_XFLAG_NODUMP | \
     547                 :            :                                   FS_XFLAG_NOATIME | FS_XFLAG_PROJINHERIT)
     548                 :            : 
     549                 :            : /* Transfer xflags flags to internal */
     550                 :          0 : static inline unsigned long ext4_xflags_to_iflags(__u32 xflags)
     551                 :            : {
     552                 :          0 :         unsigned long iflags = 0;
     553                 :            : 
     554         [ #  # ]:          0 :         if (xflags & FS_XFLAG_SYNC)
     555                 :          0 :                 iflags |= EXT4_SYNC_FL;
     556         [ #  # ]:          0 :         if (xflags & FS_XFLAG_IMMUTABLE)
     557                 :          0 :                 iflags |= EXT4_IMMUTABLE_FL;
     558         [ #  # ]:          0 :         if (xflags & FS_XFLAG_APPEND)
     559                 :          0 :                 iflags |= EXT4_APPEND_FL;
     560         [ #  # ]:          0 :         if (xflags & FS_XFLAG_NODUMP)
     561                 :          0 :                 iflags |= EXT4_NODUMP_FL;
     562         [ #  # ]:          0 :         if (xflags & FS_XFLAG_NOATIME)
     563                 :          0 :                 iflags |= EXT4_NOATIME_FL;
     564         [ #  # ]:          0 :         if (xflags & FS_XFLAG_PROJINHERIT)
     565                 :          0 :                 iflags |= EXT4_PROJINHERIT_FL;
     566                 :            : 
     567                 :          0 :         return iflags;
     568                 :            : }
     569                 :            : 
     570                 :          0 : static int ext4_shutdown(struct super_block *sb, unsigned long arg)
     571                 :            : {
     572                 :          0 :         struct ext4_sb_info *sbi = EXT4_SB(sb);
     573                 :          0 :         __u32 flags;
     574                 :            : 
     575         [ #  # ]:          0 :         if (!capable(CAP_SYS_ADMIN))
     576                 :            :                 return -EPERM;
     577                 :            : 
     578         [ #  # ]:          0 :         if (get_user(flags, (__u32 __user *)arg))
     579                 :            :                 return -EFAULT;
     580                 :            : 
     581         [ #  # ]:          0 :         if (flags > EXT4_GOING_FLAGS_NOLOGFLUSH)
     582                 :            :                 return -EINVAL;
     583                 :            : 
     584         [ #  # ]:          0 :         if (ext4_forced_shutdown(sbi))
     585                 :            :                 return 0;
     586                 :            : 
     587                 :          0 :         ext4_msg(sb, KERN_ALERT, "shut down requested (%d)", flags);
     588                 :          0 :         trace_ext4_shutdown(sb, flags);
     589                 :            : 
     590      [ #  #  # ]:          0 :         switch (flags) {
     591                 :          0 :         case EXT4_GOING_FLAGS_DEFAULT:
     592                 :          0 :                 freeze_bdev(sb->s_bdev);
     593                 :          0 :                 set_bit(EXT4_FLAGS_SHUTDOWN, &sbi->s_ext4_flags);
     594                 :          0 :                 thaw_bdev(sb->s_bdev, sb);
     595                 :          0 :                 break;
     596                 :          0 :         case EXT4_GOING_FLAGS_LOGFLUSH:
     597                 :          0 :                 set_bit(EXT4_FLAGS_SHUTDOWN, &sbi->s_ext4_flags);
     598   [ #  #  #  # ]:          0 :                 if (sbi->s_journal && !is_journal_aborted(sbi->s_journal)) {
     599                 :          0 :                         (void) ext4_force_commit(sb);
     600                 :          0 :                         jbd2_journal_abort(sbi->s_journal, -ESHUTDOWN);
     601                 :            :                 }
     602                 :            :                 break;
     603                 :          0 :         case EXT4_GOING_FLAGS_NOLOGFLUSH:
     604                 :          0 :                 set_bit(EXT4_FLAGS_SHUTDOWN, &sbi->s_ext4_flags);
     605   [ #  #  #  # ]:          0 :                 if (sbi->s_journal && !is_journal_aborted(sbi->s_journal))
     606                 :          0 :                         jbd2_journal_abort(sbi->s_journal, -ESHUTDOWN);
     607                 :            :                 break;
     608                 :            :         default:
     609                 :            :                 return -EINVAL;
     610                 :            :         }
     611                 :          0 :         clear_opt(sb, DISCARD);
     612                 :          0 :         return 0;
     613                 :            : }
     614                 :            : 
     615                 :            : struct getfsmap_info {
     616                 :            :         struct super_block      *gi_sb;
     617                 :            :         struct fsmap_head __user *gi_data;
     618                 :            :         unsigned int            gi_idx;
     619                 :            :         __u32                   gi_last_flags;
     620                 :            : };
     621                 :            : 
     622                 :          0 : static int ext4_getfsmap_format(struct ext4_fsmap *xfm, void *priv)
     623                 :            : {
     624                 :          0 :         struct getfsmap_info *info = priv;
     625                 :          0 :         struct fsmap fm;
     626                 :            : 
     627                 :          0 :         trace_ext4_getfsmap_mapping(info->gi_sb, xfm);
     628                 :            : 
     629                 :          0 :         info->gi_last_flags = xfm->fmr_flags;
     630                 :          0 :         ext4_fsmap_from_internal(info->gi_sb, &fm, xfm);
     631         [ #  # ]:          0 :         if (copy_to_user(&info->gi_data->fmh_recs[info->gi_idx++], &fm,
     632                 :            :                         sizeof(struct fsmap)))
     633                 :          0 :                 return -EFAULT;
     634                 :            : 
     635                 :            :         return 0;
     636                 :            : }
     637                 :            : 
     638                 :          0 : static int ext4_ioc_getfsmap(struct super_block *sb,
     639                 :            :                              struct fsmap_head __user *arg)
     640                 :            : {
     641                 :          0 :         struct getfsmap_info info = { NULL };
     642                 :          0 :         struct ext4_fsmap_head xhead = {0};
     643                 :          0 :         struct fsmap_head head;
     644                 :          0 :         bool aborted = false;
     645                 :          0 :         int error;
     646                 :            : 
     647         [ #  # ]:          0 :         if (copy_from_user(&head, arg, sizeof(struct fsmap_head)))
     648                 :            :                 return -EFAULT;
     649   [ #  #  #  # ]:          0 :         if (memchr_inv(head.fmh_reserved, 0, sizeof(head.fmh_reserved)) ||
     650                 :          0 :             memchr_inv(head.fmh_keys[0].fmr_reserved, 0,
     651         [ #  # ]:          0 :                        sizeof(head.fmh_keys[0].fmr_reserved)) ||
     652                 :          0 :             memchr_inv(head.fmh_keys[1].fmr_reserved, 0,
     653                 :            :                        sizeof(head.fmh_keys[1].fmr_reserved)))
     654                 :          0 :                 return -EINVAL;
     655                 :            :         /*
     656                 :            :          * ext4 doesn't report file extents at all, so the only valid
     657                 :            :          * file offsets are the magic ones (all zeroes or all ones).
     658                 :            :          */
     659         [ #  # ]:          0 :         if (head.fmh_keys[0].fmr_offset ||
     660         [ #  # ]:          0 :             (head.fmh_keys[1].fmr_offset != 0 &&
     661                 :            :              head.fmh_keys[1].fmr_offset != -1ULL))
     662                 :            :                 return -EINVAL;
     663                 :            : 
     664                 :          0 :         xhead.fmh_iflags = head.fmh_iflags;
     665                 :          0 :         xhead.fmh_count = head.fmh_count;
     666                 :          0 :         ext4_fsmap_to_internal(sb, &xhead.fmh_keys[0], &head.fmh_keys[0]);
     667                 :          0 :         ext4_fsmap_to_internal(sb, &xhead.fmh_keys[1], &head.fmh_keys[1]);
     668                 :            : 
     669                 :          0 :         trace_ext4_getfsmap_low_key(sb, &xhead.fmh_keys[0]);
     670                 :          0 :         trace_ext4_getfsmap_high_key(sb, &xhead.fmh_keys[1]);
     671                 :            : 
     672                 :          0 :         info.gi_sb = sb;
     673                 :          0 :         info.gi_data = arg;
     674                 :          0 :         error = ext4_getfsmap(sb, &xhead, ext4_getfsmap_format, &info);
     675         [ #  # ]:          0 :         if (error == EXT4_QUERY_RANGE_ABORT) {
     676                 :            :                 error = 0;
     677                 :            :                 aborted = true;
     678         [ #  # ]:          0 :         } else if (error)
     679                 :            :                 return error;
     680                 :            : 
     681                 :            :         /* If we didn't abort, set the "last" flag in the last fmx */
     682         [ #  # ]:          0 :         if (!aborted && info.gi_idx) {
     683                 :          0 :                 info.gi_last_flags |= FMR_OF_LAST;
     684         [ #  # ]:          0 :                 if (copy_to_user(&info.gi_data->fmh_recs[info.gi_idx - 1].fmr_flags,
     685                 :            :                                  &info.gi_last_flags,
     686                 :            :                                  sizeof(info.gi_last_flags)))
     687                 :            :                         return -EFAULT;
     688                 :            :         }
     689                 :            : 
     690                 :            :         /* copy back header */
     691                 :          0 :         head.fmh_entries = xhead.fmh_entries;
     692                 :          0 :         head.fmh_oflags = xhead.fmh_oflags;
     693         [ #  # ]:          0 :         if (copy_to_user(arg, &head, sizeof(struct fsmap_head)))
     694                 :          0 :                 return -EFAULT;
     695                 :            : 
     696                 :            :         return 0;
     697                 :            : }
     698                 :            : 
     699                 :          0 : static long ext4_ioctl_group_add(struct file *file,
     700                 :            :                                  struct ext4_new_group_data *input)
     701                 :            : {
     702                 :          0 :         struct super_block *sb = file_inode(file)->i_sb;
     703                 :          0 :         int err, err2=0;
     704                 :            : 
     705                 :          0 :         err = ext4_resize_begin(sb);
     706         [ #  # ]:          0 :         if (err)
     707                 :          0 :                 return err;
     708                 :            : 
     709         [ #  # ]:          0 :         if (ext4_has_feature_bigalloc(sb)) {
     710                 :          0 :                 ext4_msg(sb, KERN_ERR,
     711                 :            :                          "Online resizing not supported with bigalloc");
     712                 :          0 :                 err = -EOPNOTSUPP;
     713                 :          0 :                 goto group_add_out;
     714                 :            :         }
     715                 :            : 
     716                 :          0 :         err = mnt_want_write_file(file);
     717         [ #  # ]:          0 :         if (err)
     718                 :          0 :                 goto group_add_out;
     719                 :            : 
     720                 :          0 :         err = ext4_group_add(sb, input);
     721         [ #  # ]:          0 :         if (EXT4_SB(sb)->s_journal) {
     722                 :          0 :                 jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal);
     723                 :          0 :                 err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal);
     724                 :          0 :                 jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
     725                 :            :         }
     726         [ #  # ]:          0 :         if (err == 0)
     727                 :          0 :                 err = err2;
     728                 :          0 :         mnt_drop_write_file(file);
     729   [ #  #  #  #  :          0 :         if (!err && ext4_has_group_desc_csum(sb) &&
                   #  # ]
     730         [ #  # ]:          0 :             test_opt(sb, INIT_INODE_TABLE))
     731                 :          0 :                 err = ext4_register_li_request(sb, input->group);
     732                 :          0 : group_add_out:
     733                 :          0 :         ext4_resize_end(sb);
     734                 :          0 :         return err;
     735                 :            : }
     736                 :            : 
     737                 :          0 : static void ext4_fill_fsxattr(struct inode *inode, struct fsxattr *fa)
     738                 :            : {
     739                 :          0 :         struct ext4_inode_info *ei = EXT4_I(inode);
     740                 :            : 
     741         [ #  # ]:          0 :         simple_fill_fsxattr(fa, ext4_iflags_to_xflags(ei->i_flags &
     742                 :            :                                                       EXT4_FL_USER_VISIBLE));
     743                 :            : 
     744         [ #  # ]:          0 :         if (ext4_has_feature_project(inode->i_sb))
     745                 :          0 :                 fa->fsx_projid = from_kprojid(&init_user_ns, ei->i_projid);
     746                 :          0 : }
     747                 :            : 
     748                 :            : /* copied from fs/ioctl.c */
     749                 :          0 : static int fiemap_check_ranges(struct super_block *sb,
     750                 :            :                                u64 start, u64 len, u64 *new_len)
     751                 :            : {
     752                 :          0 :         u64 maxbytes = (u64) sb->s_maxbytes;
     753                 :            : 
     754                 :          0 :         *new_len = len;
     755                 :            : 
     756                 :          0 :         if (len == 0)
     757                 :            :                 return -EINVAL;
     758                 :            : 
     759         [ #  # ]:          0 :         if (start > maxbytes)
     760                 :            :                 return -EFBIG;
     761                 :            : 
     762                 :            :         /*
     763                 :            :          * Shrink request scope to what the fs can actually handle.
     764                 :            :          */
     765   [ #  #  #  # ]:          0 :         if (len > maxbytes || (maxbytes - len) < start)
     766                 :          0 :                 *new_len = maxbytes - start;
     767                 :            : 
     768                 :            :         return 0;
     769                 :            : }
     770                 :            : 
     771                 :            : /* So that the fiemap access checks can't overflow on 32 bit machines. */
     772                 :            : #define FIEMAP_MAX_EXTENTS      (UINT_MAX / sizeof(struct fiemap_extent))
     773                 :            : 
     774                 :          0 : static int ext4_ioctl_get_es_cache(struct file *filp, unsigned long arg)
     775                 :            : {
     776                 :          0 :         struct fiemap fiemap;
     777                 :          0 :         struct fiemap __user *ufiemap = (struct fiemap __user *) arg;
     778                 :          0 :         struct fiemap_extent_info fieinfo = { 0, };
     779                 :          0 :         struct inode *inode = file_inode(filp);
     780                 :          0 :         struct super_block *sb = inode->i_sb;
     781                 :          0 :         u64 len;
     782                 :          0 :         int error;
     783                 :            : 
     784         [ #  # ]:          0 :         if (copy_from_user(&fiemap, ufiemap, sizeof(fiemap)))
     785                 :            :                 return -EFAULT;
     786                 :            : 
     787         [ #  # ]:          0 :         if (fiemap.fm_extent_count > FIEMAP_MAX_EXTENTS)
     788                 :            :                 return -EINVAL;
     789                 :            : 
     790         [ #  # ]:          0 :         error = fiemap_check_ranges(sb, fiemap.fm_start, fiemap.fm_length,
     791                 :            :                                     &len);
     792                 :          0 :         if (error)
     793                 :          0 :                 return error;
     794                 :            : 
     795                 :          0 :         fieinfo.fi_flags = fiemap.fm_flags;
     796                 :          0 :         fieinfo.fi_extents_max = fiemap.fm_extent_count;
     797                 :          0 :         fieinfo.fi_extents_start = ufiemap->fm_extents;
     798                 :            : 
     799         [ #  # ]:          0 :         if (fiemap.fm_extent_count != 0 &&
     800   [ #  #  #  # ]:          0 :             !access_ok(fieinfo.fi_extents_start,
     801                 :            :                        fieinfo.fi_extents_max * sizeof(struct fiemap_extent)))
     802                 :            :                 return -EFAULT;
     803                 :            : 
     804         [ #  # ]:          0 :         if (fieinfo.fi_flags & FIEMAP_FLAG_SYNC)
     805                 :          0 :                 filemap_write_and_wait(inode->i_mapping);
     806                 :            : 
     807                 :          0 :         error = ext4_get_es_cache(inode, &fieinfo, fiemap.fm_start, len);
     808                 :          0 :         fiemap.fm_flags = fieinfo.fi_flags;
     809                 :          0 :         fiemap.fm_mapped_extents = fieinfo.fi_extents_mapped;
     810         [ #  # ]:          0 :         if (copy_to_user(ufiemap, &fiemap, sizeof(fiemap)))
     811                 :          0 :                 error = -EFAULT;
     812                 :            : 
     813                 :            :         return error;
     814                 :            : }
     815                 :            : 
     816                 :        330 : long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
     817                 :            : {
     818   [ -  -  -  -  :        330 :         struct inode *inode = file_inode(filp);
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
                   +  - ]
     819                 :        330 :         struct super_block *sb = inode->i_sb;
     820                 :        330 :         struct ext4_inode_info *ei = EXT4_I(inode);
     821                 :        330 :         unsigned int flags;
     822                 :            : 
     823                 :        330 :         ext4_debug("cmd = %u, arg = %lu\n", cmd, arg);
     824                 :            : 
     825   [ -  -  -  -  :        330 :         switch (cmd) {
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
                   +  - ]
     826                 :          0 :         case FS_IOC_GETFSMAP:
     827                 :          0 :                 return ext4_ioc_getfsmap(sb, (void __user *)arg);
     828                 :          0 :         case EXT4_IOC_GETFLAGS:
     829                 :          0 :                 flags = ei->i_flags & EXT4_FL_USER_VISIBLE;
     830         [ #  # ]:          0 :                 if (S_ISREG(inode->i_mode))
     831                 :          0 :                         flags &= ~EXT4_PROJINHERIT_FL;
     832                 :          0 :                 return put_user(flags, (int __user *) arg);
     833                 :          0 :         case EXT4_IOC_SETFLAGS: {
     834                 :          0 :                 int err;
     835                 :            : 
     836         [ #  # ]:          0 :                 if (!inode_owner_or_capable(inode))
     837                 :            :                         return -EACCES;
     838                 :            : 
     839         [ #  # ]:          0 :                 if (get_user(flags, (int __user *) arg))
     840                 :            :                         return -EFAULT;
     841                 :            : 
     842         [ #  # ]:          0 :                 if (flags & ~EXT4_FL_USER_VISIBLE)
     843                 :            :                         return -EOPNOTSUPP;
     844                 :            :                 /*
     845                 :            :                  * chattr(1) grabs flags via GETFLAGS, modifies the result and
     846                 :            :                  * passes that to SETFLAGS. So we cannot easily make SETFLAGS
     847                 :            :                  * more restrictive than just silently masking off visible but
     848                 :            :                  * not settable flags as we always did.
     849                 :            :                  */
     850                 :          0 :                 flags &= EXT4_FL_USER_MODIFIABLE;
     851   [ #  #  #  # ]:          0 :                 if (ext4_mask_flags(inode->i_mode, flags) != flags)
     852                 :            :                         return -EOPNOTSUPP;
     853                 :            : 
     854                 :          0 :                 err = mnt_want_write_file(filp);
     855         [ #  # ]:          0 :                 if (err)
     856                 :          0 :                         return err;
     857                 :            : 
     858                 :          0 :                 inode_lock(inode);
     859         [ #  # ]:          0 :                 err = ext4_ioctl_check_immutable(inode,
     860                 :            :                                 from_kprojid(&init_user_ns, ei->i_projid),
     861                 :            :                                 flags);
     862         [ #  # ]:          0 :                 if (!err)
     863                 :          0 :                         err = ext4_ioctl_setflags(inode, flags);
     864                 :          0 :                 inode_unlock(inode);
     865                 :          0 :                 mnt_drop_write_file(filp);
     866                 :          0 :                 return err;
     867                 :            :         }
     868                 :            :         case EXT4_IOC_GETVERSION:
     869                 :            :         case EXT4_IOC_GETVERSION_OLD:
     870                 :          0 :                 return put_user(inode->i_generation, (int __user *) arg);
     871                 :          0 :         case EXT4_IOC_SETVERSION:
     872                 :            :         case EXT4_IOC_SETVERSION_OLD: {
     873                 :          0 :                 handle_t *handle;
     874                 :          0 :                 struct ext4_iloc iloc;
     875                 :          0 :                 __u32 generation;
     876                 :          0 :                 int err;
     877                 :            : 
     878         [ #  # ]:          0 :                 if (!inode_owner_or_capable(inode))
     879                 :            :                         return -EPERM;
     880                 :            : 
     881         [ #  # ]:          0 :                 if (ext4_has_metadata_csum(inode->i_sb)) {
     882                 :          0 :                         ext4_warning(sb, "Setting inode version is not "
     883                 :            :                                      "supported with metadata_csum enabled.");
     884                 :          0 :                         return -ENOTTY;
     885                 :            :                 }
     886                 :            : 
     887                 :          0 :                 err = mnt_want_write_file(filp);
     888         [ #  # ]:          0 :                 if (err)
     889                 :          0 :                         return err;
     890         [ #  # ]:          0 :                 if (get_user(generation, (int __user *) arg)) {
     891                 :          0 :                         err = -EFAULT;
     892                 :          0 :                         goto setversion_out;
     893                 :            :                 }
     894                 :            : 
     895                 :          0 :                 inode_lock(inode);
     896                 :          0 :                 handle = ext4_journal_start(inode, EXT4_HT_INODE, 1);
     897         [ #  # ]:          0 :                 if (IS_ERR(handle)) {
     898                 :          0 :                         err = PTR_ERR(handle);
     899                 :          0 :                         goto unlock_out;
     900                 :            :                 }
     901                 :          0 :                 err = ext4_reserve_inode_write(handle, inode, &iloc);
     902         [ #  # ]:          0 :                 if (err == 0) {
     903                 :          0 :                         inode->i_ctime = current_time(inode);
     904                 :          0 :                         inode->i_generation = generation;
     905                 :          0 :                         err = ext4_mark_iloc_dirty(handle, inode, &iloc);
     906                 :            :                 }
     907                 :          0 :                 ext4_journal_stop(handle);
     908                 :            : 
     909                 :          0 : unlock_out:
     910                 :          0 :                 inode_unlock(inode);
     911                 :          0 : setversion_out:
     912                 :          0 :                 mnt_drop_write_file(filp);
     913                 :          0 :                 return err;
     914                 :            :         }
     915                 :          0 :         case EXT4_IOC_GROUP_EXTEND: {
     916                 :          0 :                 ext4_fsblk_t n_blocks_count;
     917                 :          0 :                 int err, err2=0;
     918                 :            : 
     919                 :          0 :                 err = ext4_resize_begin(sb);
     920         [ #  # ]:          0 :                 if (err)
     921                 :          0 :                         return err;
     922                 :            : 
     923         [ #  # ]:          0 :                 if (get_user(n_blocks_count, (__u32 __user *)arg)) {
     924                 :          0 :                         err = -EFAULT;
     925                 :          0 :                         goto group_extend_out;
     926                 :            :                 }
     927                 :            : 
     928         [ #  # ]:          0 :                 if (ext4_has_feature_bigalloc(sb)) {
     929                 :          0 :                         ext4_msg(sb, KERN_ERR,
     930                 :            :                                  "Online resizing not supported with bigalloc");
     931                 :          0 :                         err = -EOPNOTSUPP;
     932                 :          0 :                         goto group_extend_out;
     933                 :            :                 }
     934                 :            : 
     935                 :          0 :                 err = mnt_want_write_file(filp);
     936         [ #  # ]:          0 :                 if (err)
     937                 :          0 :                         goto group_extend_out;
     938                 :            : 
     939                 :          0 :                 err = ext4_group_extend(sb, EXT4_SB(sb)->s_es, n_blocks_count);
     940         [ #  # ]:          0 :                 if (EXT4_SB(sb)->s_journal) {
     941                 :          0 :                         jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal);
     942                 :          0 :                         err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal);
     943                 :          0 :                         jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
     944                 :            :                 }
     945         [ #  # ]:          0 :                 if (err == 0)
     946                 :          0 :                         err = err2;
     947                 :          0 :                 mnt_drop_write_file(filp);
     948                 :          0 : group_extend_out:
     949                 :          0 :                 ext4_resize_end(sb);
     950                 :          0 :                 return err;
     951                 :            :         }
     952                 :            : 
     953                 :          0 :         case EXT4_IOC_MOVE_EXT: {
     954                 :          0 :                 struct move_extent me;
     955                 :          0 :                 struct fd donor;
     956                 :          0 :                 int err;
     957                 :            : 
     958         [ #  # ]:          0 :                 if (!(filp->f_mode & FMODE_READ) ||
     959                 :            :                     !(filp->f_mode & FMODE_WRITE))
     960                 :            :                         return -EBADF;
     961                 :            : 
     962         [ #  # ]:          0 :                 if (copy_from_user(&me,
     963                 :            :                         (struct move_extent __user *)arg, sizeof(me)))
     964                 :            :                         return -EFAULT;
     965                 :          0 :                 me.moved_len = 0;
     966                 :            : 
     967                 :          0 :                 donor = fdget(me.donor_fd);
     968         [ #  # ]:          0 :                 if (!donor.file)
     969                 :            :                         return -EBADF;
     970                 :            : 
     971         [ #  # ]:          0 :                 if (!(donor.file->f_mode & FMODE_WRITE)) {
     972                 :          0 :                         err = -EBADF;
     973                 :          0 :                         goto mext_out;
     974                 :            :                 }
     975                 :            : 
     976         [ #  # ]:          0 :                 if (ext4_has_feature_bigalloc(sb)) {
     977                 :          0 :                         ext4_msg(sb, KERN_ERR,
     978                 :            :                                  "Online defrag not supported with bigalloc");
     979                 :          0 :                         err = -EOPNOTSUPP;
     980                 :          0 :                         goto mext_out;
     981                 :          0 :                 } else if (IS_DAX(inode)) {
     982                 :            :                         ext4_msg(sb, KERN_ERR,
     983                 :            :                                  "Online defrag not supported with DAX");
     984                 :            :                         err = -EOPNOTSUPP;
     985                 :            :                         goto mext_out;
     986                 :            :                 }
     987                 :            : 
     988                 :          0 :                 err = mnt_want_write_file(filp);
     989         [ #  # ]:          0 :                 if (err)
     990                 :          0 :                         goto mext_out;
     991                 :            : 
     992                 :          0 :                 err = ext4_move_extents(filp, donor.file, me.orig_start,
     993                 :            :                                         me.donor_start, me.len, &me.moved_len);
     994                 :          0 :                 mnt_drop_write_file(filp);
     995                 :            : 
     996         [ #  # ]:          0 :                 if (copy_to_user((struct move_extent __user *)arg,
     997                 :            :                                  &me, sizeof(me)))
     998                 :          0 :                         err = -EFAULT;
     999                 :          0 : mext_out:
    1000         [ #  # ]:          0 :                 fdput(donor);
    1001                 :          0 :                 return err;
    1002                 :            :         }
    1003                 :            : 
    1004                 :          0 :         case EXT4_IOC_GROUP_ADD: {
    1005                 :          0 :                 struct ext4_new_group_data input;
    1006                 :            : 
    1007         [ #  # ]:          0 :                 if (copy_from_user(&input, (struct ext4_new_group_input __user *)arg,
    1008                 :            :                                 sizeof(input)))
    1009                 :            :                         return -EFAULT;
    1010                 :            : 
    1011                 :          0 :                 return ext4_ioctl_group_add(filp, &input);
    1012                 :            :         }
    1013                 :            : 
    1014                 :          0 :         case EXT4_IOC_MIGRATE:
    1015                 :            :         {
    1016                 :          0 :                 int err;
    1017         [ #  # ]:          0 :                 if (!inode_owner_or_capable(inode))
    1018                 :            :                         return -EACCES;
    1019                 :            : 
    1020                 :          0 :                 err = mnt_want_write_file(filp);
    1021         [ #  # ]:          0 :                 if (err)
    1022                 :          0 :                         return err;
    1023                 :            :                 /*
    1024                 :            :                  * inode_mutex prevent write and truncate on the file.
    1025                 :            :                  * Read still goes through. We take i_data_sem in
    1026                 :            :                  * ext4_ext_swap_inode_data before we switch the
    1027                 :            :                  * inode format to prevent read.
    1028                 :            :                  */
    1029                 :          0 :                 inode_lock((inode));
    1030                 :          0 :                 err = ext4_ext_migrate(inode);
    1031                 :          0 :                 inode_unlock((inode));
    1032                 :          0 :                 mnt_drop_write_file(filp);
    1033                 :          0 :                 return err;
    1034                 :            :         }
    1035                 :            : 
    1036                 :          0 :         case EXT4_IOC_ALLOC_DA_BLKS:
    1037                 :            :         {
    1038                 :          0 :                 int err;
    1039         [ #  # ]:          0 :                 if (!inode_owner_or_capable(inode))
    1040                 :            :                         return -EACCES;
    1041                 :            : 
    1042                 :          0 :                 err = mnt_want_write_file(filp);
    1043         [ #  # ]:          0 :                 if (err)
    1044                 :          0 :                         return err;
    1045                 :          0 :                 err = ext4_alloc_da_blocks(inode);
    1046                 :          0 :                 mnt_drop_write_file(filp);
    1047                 :          0 :                 return err;
    1048                 :            :         }
    1049                 :            : 
    1050                 :          0 :         case EXT4_IOC_SWAP_BOOT:
    1051                 :            :         {
    1052                 :          0 :                 int err;
    1053         [ #  # ]:          0 :                 if (!(filp->f_mode & FMODE_WRITE))
    1054                 :            :                         return -EBADF;
    1055                 :          0 :                 err = mnt_want_write_file(filp);
    1056         [ #  # ]:          0 :                 if (err)
    1057                 :          0 :                         return err;
    1058                 :          0 :                 err = swap_inode_boot_loader(sb, inode);
    1059                 :          0 :                 mnt_drop_write_file(filp);
    1060                 :          0 :                 return err;
    1061                 :            :         }
    1062                 :            : 
    1063                 :          0 :         case EXT4_IOC_RESIZE_FS: {
    1064                 :          0 :                 ext4_fsblk_t n_blocks_count;
    1065                 :          0 :                 int err = 0, err2 = 0;
    1066                 :          0 :                 ext4_group_t o_group = EXT4_SB(sb)->s_groups_count;
    1067                 :            : 
    1068         [ #  # ]:          0 :                 if (copy_from_user(&n_blocks_count, (__u64 __user *)arg,
    1069                 :            :                                    sizeof(__u64))) {
    1070                 :            :                         return -EFAULT;
    1071                 :            :                 }
    1072                 :            : 
    1073                 :          0 :                 err = ext4_resize_begin(sb);
    1074         [ #  # ]:          0 :                 if (err)
    1075                 :          0 :                         return err;
    1076                 :            : 
    1077                 :          0 :                 err = mnt_want_write_file(filp);
    1078         [ #  # ]:          0 :                 if (err)
    1079                 :          0 :                         goto resizefs_out;
    1080                 :            : 
    1081                 :          0 :                 err = ext4_resize_fs(sb, n_blocks_count);
    1082         [ #  # ]:          0 :                 if (EXT4_SB(sb)->s_journal) {
    1083                 :          0 :                         jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal);
    1084                 :          0 :                         err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal);
    1085                 :          0 :                         jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
    1086                 :            :                 }
    1087         [ #  # ]:          0 :                 if (err == 0)
    1088                 :          0 :                         err = err2;
    1089                 :          0 :                 mnt_drop_write_file(filp);
    1090   [ #  #  #  #  :          0 :                 if (!err && (o_group < EXT4_SB(sb)->s_groups_count) &&
                   #  # ]
    1091         [ #  # ]:          0 :                     ext4_has_group_desc_csum(sb) &&
    1092         [ #  # ]:          0 :                     test_opt(sb, INIT_INODE_TABLE))
    1093                 :          0 :                         err = ext4_register_li_request(sb, o_group);
    1094                 :            : 
    1095                 :          0 : resizefs_out:
    1096                 :          0 :                 ext4_resize_end(sb);
    1097                 :          0 :                 return err;
    1098                 :            :         }
    1099                 :            : 
    1100                 :          0 :         case FITRIM:
    1101                 :            :         {
    1102                 :          0 :                 struct request_queue *q = bdev_get_queue(sb->s_bdev);
    1103                 :          0 :                 struct fstrim_range range;
    1104                 :          0 :                 int ret = 0;
    1105                 :            : 
    1106         [ #  # ]:          0 :                 if (!capable(CAP_SYS_ADMIN))
    1107                 :            :                         return -EPERM;
    1108                 :            : 
    1109         [ #  # ]:          0 :                 if (!blk_queue_discard(q))
    1110                 :            :                         return -EOPNOTSUPP;
    1111                 :            : 
    1112                 :            :                 /*
    1113                 :            :                  * We haven't replayed the journal, so we cannot use our
    1114                 :            :                  * block-bitmap-guided storage zapping commands.
    1115                 :            :                  */
    1116   [ #  #  #  # ]:          0 :                 if (test_opt(sb, NOLOAD) && ext4_has_feature_journal(sb))
    1117                 :            :                         return -EROFS;
    1118                 :            : 
    1119         [ #  # ]:          0 :                 if (copy_from_user(&range, (struct fstrim_range __user *)arg,
    1120                 :            :                     sizeof(range)))
    1121                 :            :                         return -EFAULT;
    1122                 :            : 
    1123                 :          0 :                 range.minlen = max((unsigned int)range.minlen,
    1124                 :            :                                    q->limits.discard_granularity);
    1125                 :          0 :                 ret = ext4_trim_fs(sb, &range);
    1126         [ #  # ]:          0 :                 if (ret < 0)
    1127                 :          0 :                         return ret;
    1128                 :            : 
    1129         [ #  # ]:          0 :                 if (copy_to_user((struct fstrim_range __user *)arg, &range,
    1130                 :            :                     sizeof(range)))
    1131                 :          0 :                         return -EFAULT;
    1132                 :            : 
    1133                 :            :                 return 0;
    1134                 :            :         }
    1135                 :          0 :         case EXT4_IOC_PRECACHE_EXTENTS:
    1136                 :          0 :                 return ext4_ext_precache(inode);
    1137                 :            : 
    1138                 :            :         case EXT4_IOC_SET_ENCRYPTION_POLICY:
    1139                 :          0 :                 if (!ext4_has_feature_encrypt(sb))
    1140                 :            :                         return -EOPNOTSUPP;
    1141                 :            :                 return fscrypt_ioctl_set_policy(filp, (const void __user *)arg);
    1142                 :            : 
    1143                 :            :         case EXT4_IOC_GET_ENCRYPTION_PWSALT: {
    1144                 :            : #ifdef CONFIG_FS_ENCRYPTION
    1145                 :            :                 int err, err2;
    1146                 :            :                 struct ext4_sb_info *sbi = EXT4_SB(sb);
    1147                 :            :                 handle_t *handle;
    1148                 :            : 
    1149                 :            :                 if (!ext4_has_feature_encrypt(sb))
    1150                 :            :                         return -EOPNOTSUPP;
    1151                 :            :                 if (uuid_is_zero(sbi->s_es->s_encrypt_pw_salt)) {
    1152                 :            :                         err = mnt_want_write_file(filp);
    1153                 :            :                         if (err)
    1154                 :            :                                 return err;
    1155                 :            :                         handle = ext4_journal_start_sb(sb, EXT4_HT_MISC, 1);
    1156                 :            :                         if (IS_ERR(handle)) {
    1157                 :            :                                 err = PTR_ERR(handle);
    1158                 :            :                                 goto pwsalt_err_exit;
    1159                 :            :                         }
    1160                 :            :                         err = ext4_journal_get_write_access(handle, sbi->s_sbh);
    1161                 :            :                         if (err)
    1162                 :            :                                 goto pwsalt_err_journal;
    1163                 :            :                         generate_random_uuid(sbi->s_es->s_encrypt_pw_salt);
    1164                 :            :                         err = ext4_handle_dirty_metadata(handle, NULL,
    1165                 :            :                                                          sbi->s_sbh);
    1166                 :            :                 pwsalt_err_journal:
    1167                 :            :                         err2 = ext4_journal_stop(handle);
    1168                 :            :                         if (err2 && !err)
    1169                 :            :                                 err = err2;
    1170                 :            :                 pwsalt_err_exit:
    1171                 :            :                         mnt_drop_write_file(filp);
    1172                 :            :                         if (err)
    1173                 :            :                                 return err;
    1174                 :            :                 }
    1175                 :            :                 if (copy_to_user((void __user *) arg,
    1176                 :            :                                  sbi->s_es->s_encrypt_pw_salt, 16))
    1177                 :            :                         return -EFAULT;
    1178                 :            :                 return 0;
    1179                 :            : #else
    1180                 :            :                 return -EOPNOTSUPP;
    1181                 :            : #endif
    1182                 :            :         }
    1183                 :            :         case EXT4_IOC_GET_ENCRYPTION_POLICY:
    1184                 :          0 :                 if (!ext4_has_feature_encrypt(sb))
    1185                 :            :                         return -EOPNOTSUPP;
    1186                 :            :                 return fscrypt_ioctl_get_policy(filp, (void __user *)arg);
    1187                 :            : 
    1188                 :            :         case FS_IOC_GET_ENCRYPTION_POLICY_EX:
    1189                 :          0 :                 if (!ext4_has_feature_encrypt(sb))
    1190                 :            :                         return -EOPNOTSUPP;
    1191                 :            :                 return fscrypt_ioctl_get_policy_ex(filp, (void __user *)arg);
    1192                 :            : 
    1193                 :            :         case FS_IOC_ADD_ENCRYPTION_KEY:
    1194                 :          0 :                 if (!ext4_has_feature_encrypt(sb))
    1195                 :            :                         return -EOPNOTSUPP;
    1196                 :            :                 return fscrypt_ioctl_add_key(filp, (void __user *)arg);
    1197                 :            : 
    1198                 :            :         case FS_IOC_REMOVE_ENCRYPTION_KEY:
    1199                 :          0 :                 if (!ext4_has_feature_encrypt(sb))
    1200                 :            :                         return -EOPNOTSUPP;
    1201                 :            :                 return fscrypt_ioctl_remove_key(filp, (void __user *)arg);
    1202                 :            : 
    1203                 :            :         case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS:
    1204                 :          0 :                 if (!ext4_has_feature_encrypt(sb))
    1205                 :            :                         return -EOPNOTSUPP;
    1206                 :            :                 return fscrypt_ioctl_remove_key_all_users(filp,
    1207                 :            :                                                           (void __user *)arg);
    1208                 :            :         case FS_IOC_GET_ENCRYPTION_KEY_STATUS:
    1209                 :          0 :                 if (!ext4_has_feature_encrypt(sb))
    1210                 :            :                         return -EOPNOTSUPP;
    1211                 :            :                 return fscrypt_ioctl_get_key_status(filp, (void __user *)arg);
    1212                 :            : 
    1213                 :          0 :         case EXT4_IOC_CLEAR_ES_CACHE:
    1214                 :            :         {
    1215         [ #  # ]:          0 :                 if (!inode_owner_or_capable(inode))
    1216                 :            :                         return -EACCES;
    1217                 :          0 :                 ext4_clear_inode_es(inode);
    1218                 :          0 :                 return 0;
    1219                 :            :         }
    1220                 :            : 
    1221                 :          0 :         case EXT4_IOC_GETSTATE:
    1222                 :            :         {
    1223                 :          0 :                 __u32   state = 0;
    1224                 :            : 
    1225         [ #  # ]:          0 :                 if (ext4_test_inode_state(inode, EXT4_STATE_EXT_PRECACHED))
    1226                 :          0 :                         state |= EXT4_STATE_FLAG_EXT_PRECACHED;
    1227         [ #  # ]:          0 :                 if (ext4_test_inode_state(inode, EXT4_STATE_NEW))
    1228                 :          0 :                         state |= EXT4_STATE_FLAG_NEW;
    1229         [ #  # ]:          0 :                 if (ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY))
    1230                 :          0 :                         state |= EXT4_STATE_FLAG_NEWENTRY;
    1231         [ #  # ]:          0 :                 if (ext4_test_inode_state(inode, EXT4_STATE_DA_ALLOC_CLOSE))
    1232                 :          0 :                         state |= EXT4_STATE_FLAG_DA_ALLOC_CLOSE;
    1233                 :            : 
    1234                 :          0 :                 return put_user(state, (__u32 __user *) arg);
    1235                 :            :         }
    1236                 :            : 
    1237                 :          0 :         case EXT4_IOC_GET_ES_CACHE:
    1238                 :          0 :                 return ext4_ioctl_get_es_cache(filp, arg);
    1239                 :            : 
    1240                 :          0 :         case EXT4_IOC_FSGETXATTR:
    1241                 :            :         {
    1242                 :          0 :                 struct fsxattr fa;
    1243                 :            : 
    1244                 :          0 :                 ext4_fill_fsxattr(inode, &fa);
    1245                 :            : 
    1246         [ #  # ]:          0 :                 if (copy_to_user((struct fsxattr __user *)arg,
    1247                 :            :                                  &fa, sizeof(fa)))
    1248                 :          0 :                         return -EFAULT;
    1249                 :            :                 return 0;
    1250                 :            :         }
    1251                 :          0 :         case EXT4_IOC_FSSETXATTR:
    1252                 :            :         {
    1253                 :          0 :                 struct fsxattr fa, old_fa;
    1254                 :          0 :                 int err;
    1255                 :            : 
    1256         [ #  # ]:          0 :                 if (copy_from_user(&fa, (struct fsxattr __user *)arg,
    1257                 :            :                                    sizeof(fa)))
    1258                 :            :                         return -EFAULT;
    1259                 :            : 
    1260                 :            :                 /* Make sure caller has proper permission */
    1261         [ #  # ]:          0 :                 if (!inode_owner_or_capable(inode))
    1262                 :            :                         return -EACCES;
    1263                 :            : 
    1264         [ #  # ]:          0 :                 if (fa.fsx_xflags & ~EXT4_SUPPORTED_FS_XFLAGS)
    1265                 :            :                         return -EOPNOTSUPP;
    1266                 :            : 
    1267                 :          0 :                 flags = ext4_xflags_to_iflags(fa.fsx_xflags);
    1268   [ #  #  #  # ]:          0 :                 if (ext4_mask_flags(inode->i_mode, flags) != flags)
    1269                 :            :                         return -EOPNOTSUPP;
    1270                 :            : 
    1271                 :          0 :                 err = mnt_want_write_file(filp);
    1272         [ #  # ]:          0 :                 if (err)
    1273                 :          0 :                         return err;
    1274                 :            : 
    1275                 :          0 :                 inode_lock(inode);
    1276                 :          0 :                 ext4_fill_fsxattr(inode, &old_fa);
    1277                 :          0 :                 err = vfs_ioc_fssetxattr_check(inode, &old_fa, &fa);
    1278         [ #  # ]:          0 :                 if (err)
    1279                 :          0 :                         goto out;
    1280                 :          0 :                 flags = (ei->i_flags & ~EXT4_FL_XFLAG_VISIBLE) |
    1281                 :          0 :                          (flags & EXT4_FL_XFLAG_VISIBLE);
    1282                 :          0 :                 err = ext4_ioctl_check_immutable(inode, fa.fsx_projid, flags);
    1283         [ #  # ]:          0 :                 if (err)
    1284                 :          0 :                         goto out;
    1285                 :          0 :                 err = ext4_ioctl_setflags(inode, flags);
    1286         [ #  # ]:          0 :                 if (err)
    1287                 :          0 :                         goto out;
    1288                 :          0 :                 err = ext4_ioctl_setproject(filp, fa.fsx_projid);
    1289                 :          0 : out:
    1290                 :          0 :                 inode_unlock(inode);
    1291                 :          0 :                 mnt_drop_write_file(filp);
    1292                 :          0 :                 return err;
    1293                 :            :         }
    1294                 :          0 :         case EXT4_IOC_SHUTDOWN:
    1295                 :          0 :                 return ext4_shutdown(sb, arg);
    1296                 :            : 
    1297                 :            :         case FS_IOC_ENABLE_VERITY:
    1298                 :          0 :                 if (!ext4_has_feature_verity(sb))
    1299                 :            :                         return -EOPNOTSUPP;
    1300                 :            :                 return fsverity_ioctl_enable(filp, (const void __user *)arg);
    1301                 :            : 
    1302                 :            :         case FS_IOC_MEASURE_VERITY:
    1303                 :          0 :                 if (!ext4_has_feature_verity(sb))
    1304                 :            :                         return -EOPNOTSUPP;
    1305                 :            :                 return fsverity_ioctl_measure(filp, (void __user *)arg);
    1306                 :            : 
    1307                 :        330 :         default:
    1308                 :        330 :                 return -ENOTTY;
    1309                 :            :         }
    1310                 :            : }
    1311                 :            : 
    1312                 :            : #ifdef CONFIG_COMPAT
    1313                 :          0 : long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
    1314                 :            : {
    1315                 :            :         /* These are just misnamed, they actually get/put from/to user an int */
    1316   [ #  #  #  #  :          0 :         switch (cmd) {
          #  #  #  #  #  
                #  #  # ]
    1317                 :          0 :         case EXT4_IOC32_GETFLAGS:
    1318                 :          0 :                 cmd = EXT4_IOC_GETFLAGS;
    1319                 :          0 :                 break;
    1320                 :          0 :         case EXT4_IOC32_SETFLAGS:
    1321                 :          0 :                 cmd = EXT4_IOC_SETFLAGS;
    1322                 :          0 :                 break;
    1323                 :          0 :         case EXT4_IOC32_GETVERSION:
    1324                 :          0 :                 cmd = EXT4_IOC_GETVERSION;
    1325                 :          0 :                 break;
    1326                 :          0 :         case EXT4_IOC32_SETVERSION:
    1327                 :          0 :                 cmd = EXT4_IOC_SETVERSION;
    1328                 :          0 :                 break;
    1329                 :          0 :         case EXT4_IOC32_GROUP_EXTEND:
    1330                 :          0 :                 cmd = EXT4_IOC_GROUP_EXTEND;
    1331                 :          0 :                 break;
    1332                 :          0 :         case EXT4_IOC32_GETVERSION_OLD:
    1333                 :          0 :                 cmd = EXT4_IOC_GETVERSION_OLD;
    1334                 :          0 :                 break;
    1335                 :          0 :         case EXT4_IOC32_SETVERSION_OLD:
    1336                 :          0 :                 cmd = EXT4_IOC_SETVERSION_OLD;
    1337                 :          0 :                 break;
    1338                 :          0 :         case EXT4_IOC32_GETRSVSZ:
    1339                 :          0 :                 cmd = EXT4_IOC_GETRSVSZ;
    1340                 :          0 :                 break;
    1341                 :          0 :         case EXT4_IOC32_SETRSVSZ:
    1342                 :          0 :                 cmd = EXT4_IOC_SETRSVSZ;
    1343                 :          0 :                 break;
    1344                 :          0 :         case EXT4_IOC32_GROUP_ADD: {
    1345                 :          0 :                 struct compat_ext4_new_group_input __user *uinput;
    1346                 :          0 :                 struct ext4_new_group_data input;
    1347                 :          0 :                 int err;
    1348                 :            : 
    1349                 :          0 :                 uinput = compat_ptr(arg);
    1350                 :          0 :                 err = get_user(input.group, &uinput->group);
    1351                 :          0 :                 err |= get_user(input.block_bitmap, &uinput->block_bitmap);
    1352                 :          0 :                 err |= get_user(input.inode_bitmap, &uinput->inode_bitmap);
    1353                 :          0 :                 err |= get_user(input.inode_table, &uinput->inode_table);
    1354                 :          0 :                 err |= get_user(input.blocks_count, &uinput->blocks_count);
    1355                 :          0 :                 err |= get_user(input.reserved_blocks,
    1356                 :            :                                 &uinput->reserved_blocks);
    1357         [ #  # ]:          0 :                 if (err)
    1358                 :            :                         return -EFAULT;
    1359                 :          0 :                 return ext4_ioctl_group_add(file, &input);
    1360                 :            :         }
    1361                 :            :         case EXT4_IOC_MOVE_EXT:
    1362                 :            :         case EXT4_IOC_RESIZE_FS:
    1363                 :            :         case FITRIM:
    1364                 :            :         case EXT4_IOC_PRECACHE_EXTENTS:
    1365                 :            :         case EXT4_IOC_SET_ENCRYPTION_POLICY:
    1366                 :            :         case EXT4_IOC_GET_ENCRYPTION_PWSALT:
    1367                 :            :         case EXT4_IOC_GET_ENCRYPTION_POLICY:
    1368                 :            :         case FS_IOC_GET_ENCRYPTION_POLICY_EX:
    1369                 :            :         case FS_IOC_ADD_ENCRYPTION_KEY:
    1370                 :            :         case FS_IOC_REMOVE_ENCRYPTION_KEY:
    1371                 :            :         case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS:
    1372                 :            :         case FS_IOC_GET_ENCRYPTION_KEY_STATUS:
    1373                 :            :         case EXT4_IOC_SHUTDOWN:
    1374                 :            :         case FS_IOC_GETFSMAP:
    1375                 :            :         case FS_IOC_ENABLE_VERITY:
    1376                 :            :         case FS_IOC_MEASURE_VERITY:
    1377                 :            :         case EXT4_IOC_CLEAR_ES_CACHE:
    1378                 :            :         case EXT4_IOC_GETSTATE:
    1379                 :            :         case EXT4_IOC_GET_ES_CACHE:
    1380                 :            :         case EXT4_IOC_FSGETXATTR:
    1381                 :            :         case EXT4_IOC_FSSETXATTR:
    1382                 :            :                 break;
    1383                 :            :         default:
    1384                 :            :                 return -ENOIOCTLCMD;
    1385                 :            :         }
    1386                 :          0 :         return ext4_ioctl(file, cmd, (unsigned long) compat_ptr(arg));
    1387                 :            : }
    1388                 :            : #endif

Generated by: LCOV version 1.14