1ac27a0ecSDave Kleikamp /* 2617ba13bSMingming Cao * linux/fs/ext4/ioctl.c 3ac27a0ecSDave Kleikamp * 4ac27a0ecSDave Kleikamp * Copyright (C) 1993, 1994, 1995 5ac27a0ecSDave Kleikamp * Remy Card (card@masi.ibp.fr) 6ac27a0ecSDave Kleikamp * Laboratoire MASI - Institut Blaise Pascal 7ac27a0ecSDave Kleikamp * Universite Pierre et Marie Curie (Paris VI) 8ac27a0ecSDave Kleikamp */ 9ac27a0ecSDave Kleikamp 10ac27a0ecSDave Kleikamp #include <linux/fs.h> 11dab291afSMingming Cao #include <linux/jbd2.h> 12ac27a0ecSDave Kleikamp #include <linux/capability.h> 13ac27a0ecSDave Kleikamp #include <linux/time.h> 14ac27a0ecSDave Kleikamp #include <linux/compat.h> 1542a74f20SDave Hansen #include <linux/mount.h> 16748de673SAkira Fujita #include <linux/file.h> 17ac27a0ecSDave Kleikamp #include <asm/uaccess.h> 183dcf5451SChristoph Hellwig #include "ext4_jbd2.h" 193dcf5451SChristoph Hellwig #include "ext4.h" 20ac27a0ecSDave Kleikamp 215cdd7b2dSAndi Kleen long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 22ac27a0ecSDave Kleikamp { 235cdd7b2dSAndi Kleen struct inode *inode = filp->f_dentry->d_inode; 24bab08ab9STheodore Ts'o struct super_block *sb = inode->i_sb; 25617ba13bSMingming Cao struct ext4_inode_info *ei = EXT4_I(inode); 26ac27a0ecSDave Kleikamp unsigned int flags; 27ac27a0ecSDave Kleikamp 28617ba13bSMingming Cao ext4_debug("cmd = %u, arg = %lu\n", cmd, arg); 29ac27a0ecSDave Kleikamp 30ac27a0ecSDave Kleikamp switch (cmd) { 31617ba13bSMingming Cao case EXT4_IOC_GETFLAGS: 32ff9ddf7eSJan Kara ext4_get_inode_flags(ei); 33617ba13bSMingming Cao flags = ei->i_flags & EXT4_FL_USER_VISIBLE; 34ac27a0ecSDave Kleikamp return put_user(flags, (int __user *) arg); 35617ba13bSMingming Cao case EXT4_IOC_SETFLAGS: { 36ac27a0ecSDave Kleikamp handle_t *handle = NULL; 374db46fc2SAneesh Kumar K.V int err, migrate = 0; 38617ba13bSMingming Cao struct ext4_iloc iloc; 39ac27a0ecSDave Kleikamp unsigned int oldflags; 40ac27a0ecSDave Kleikamp unsigned int jflag; 41ac27a0ecSDave Kleikamp 422e149670SSerge E. Hallyn if (!inode_owner_or_capable(inode)) 43ac27a0ecSDave Kleikamp return -EACCES; 44ac27a0ecSDave Kleikamp 45ac27a0ecSDave Kleikamp if (get_user(flags, (int __user *) arg)) 46ac27a0ecSDave Kleikamp return -EFAULT; 47ac27a0ecSDave Kleikamp 4842a74f20SDave Hansen err = mnt_want_write(filp->f_path.mnt); 4942a74f20SDave Hansen if (err) 5042a74f20SDave Hansen return err; 5142a74f20SDave Hansen 522dc6b0d4SDuane Griffin flags = ext4_mask_flags(inode->i_mode, flags); 53ac27a0ecSDave Kleikamp 5442a74f20SDave Hansen err = -EPERM; 55ac27a0ecSDave Kleikamp mutex_lock(&inode->i_mutex); 56e47776a0SJan Kara /* Is it quota file? Do not allow user to mess with it */ 5742a74f20SDave Hansen if (IS_NOQUOTA(inode)) 5842a74f20SDave Hansen goto flags_out; 5942a74f20SDave Hansen 60ac27a0ecSDave Kleikamp oldflags = ei->i_flags; 61ac27a0ecSDave Kleikamp 62ac27a0ecSDave Kleikamp /* The JOURNAL_DATA flag is modifiable only by root */ 63617ba13bSMingming Cao jflag = flags & EXT4_JOURNAL_DATA_FL; 64ac27a0ecSDave Kleikamp 65ac27a0ecSDave Kleikamp /* 66ac27a0ecSDave Kleikamp * The IMMUTABLE and APPEND_ONLY flags can only be changed by 67ac27a0ecSDave Kleikamp * the relevant capability. 68ac27a0ecSDave Kleikamp * 69ac27a0ecSDave Kleikamp * This test looks nicer. Thanks to Pauline Middelink 70ac27a0ecSDave Kleikamp */ 71617ba13bSMingming Cao if ((flags ^ oldflags) & (EXT4_APPEND_FL | EXT4_IMMUTABLE_FL)) { 7242a74f20SDave Hansen if (!capable(CAP_LINUX_IMMUTABLE)) 7342a74f20SDave Hansen goto flags_out; 74ac27a0ecSDave Kleikamp } 75ac27a0ecSDave Kleikamp 76ac27a0ecSDave Kleikamp /* 77ac27a0ecSDave Kleikamp * The JOURNAL_DATA flag can only be changed by 78ac27a0ecSDave Kleikamp * the relevant capability. 79ac27a0ecSDave Kleikamp */ 80617ba13bSMingming Cao if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) { 8142a74f20SDave Hansen if (!capable(CAP_SYS_RESOURCE)) 8242a74f20SDave Hansen goto flags_out; 83ac27a0ecSDave Kleikamp } 844db46fc2SAneesh Kumar K.V if (oldflags & EXT4_EXTENTS_FL) { 854db46fc2SAneesh Kumar K.V /* We don't support clearning extent flags */ 864db46fc2SAneesh Kumar K.V if (!(flags & EXT4_EXTENTS_FL)) { 874db46fc2SAneesh Kumar K.V err = -EOPNOTSUPP; 884db46fc2SAneesh Kumar K.V goto flags_out; 894db46fc2SAneesh Kumar K.V } 904db46fc2SAneesh Kumar K.V } else if (flags & EXT4_EXTENTS_FL) { 914db46fc2SAneesh Kumar K.V /* migrate the file */ 924db46fc2SAneesh Kumar K.V migrate = 1; 934db46fc2SAneesh Kumar K.V flags &= ~EXT4_EXTENTS_FL; 944db46fc2SAneesh Kumar K.V } 95ac27a0ecSDave Kleikamp 96c8d46e41SJiaying Zhang if (flags & EXT4_EOFBLOCKS_FL) { 97c8d46e41SJiaying Zhang /* we don't support adding EOFBLOCKS flag */ 98c8d46e41SJiaying Zhang if (!(oldflags & EXT4_EOFBLOCKS_FL)) { 99c8d46e41SJiaying Zhang err = -EOPNOTSUPP; 100c8d46e41SJiaying Zhang goto flags_out; 101c8d46e41SJiaying Zhang } 102c8d46e41SJiaying Zhang } else if (oldflags & EXT4_EOFBLOCKS_FL) 103c8d46e41SJiaying Zhang ext4_truncate(inode); 104c8d46e41SJiaying Zhang 105617ba13bSMingming Cao handle = ext4_journal_start(inode, 1); 106ac27a0ecSDave Kleikamp if (IS_ERR(handle)) { 10742a74f20SDave Hansen err = PTR_ERR(handle); 10842a74f20SDave Hansen goto flags_out; 109ac27a0ecSDave Kleikamp } 110ac27a0ecSDave Kleikamp if (IS_SYNC(inode)) 1110390131bSFrank Mayhar ext4_handle_sync(handle); 112617ba13bSMingming Cao err = ext4_reserve_inode_write(handle, inode, &iloc); 113ac27a0ecSDave Kleikamp if (err) 114ac27a0ecSDave Kleikamp goto flags_err; 115ac27a0ecSDave Kleikamp 116617ba13bSMingming Cao flags = flags & EXT4_FL_USER_MODIFIABLE; 117617ba13bSMingming Cao flags |= oldflags & ~EXT4_FL_USER_MODIFIABLE; 118ac27a0ecSDave Kleikamp ei->i_flags = flags; 119ac27a0ecSDave Kleikamp 120617ba13bSMingming Cao ext4_set_inode_flags(inode); 121ef7f3835SKalpak Shah inode->i_ctime = ext4_current_time(inode); 122ac27a0ecSDave Kleikamp 123617ba13bSMingming Cao err = ext4_mark_iloc_dirty(handle, inode, &iloc); 124ac27a0ecSDave Kleikamp flags_err: 125617ba13bSMingming Cao ext4_journal_stop(handle); 12642a74f20SDave Hansen if (err) 12742a74f20SDave Hansen goto flags_out; 128ac27a0ecSDave Kleikamp 129617ba13bSMingming Cao if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) 130617ba13bSMingming Cao err = ext4_change_inode_journal_flag(inode, jflag); 1314db46fc2SAneesh Kumar K.V if (err) 1324db46fc2SAneesh Kumar K.V goto flags_out; 1334db46fc2SAneesh Kumar K.V if (migrate) 1344db46fc2SAneesh Kumar K.V err = ext4_ext_migrate(inode); 13542a74f20SDave Hansen flags_out: 136ac27a0ecSDave Kleikamp mutex_unlock(&inode->i_mutex); 13742a74f20SDave Hansen mnt_drop_write(filp->f_path.mnt); 138ac27a0ecSDave Kleikamp return err; 139ac27a0ecSDave Kleikamp } 140617ba13bSMingming Cao case EXT4_IOC_GETVERSION: 141617ba13bSMingming Cao case EXT4_IOC_GETVERSION_OLD: 142ac27a0ecSDave Kleikamp return put_user(inode->i_generation, (int __user *) arg); 143617ba13bSMingming Cao case EXT4_IOC_SETVERSION: 144617ba13bSMingming Cao case EXT4_IOC_SETVERSION_OLD: { 145ac27a0ecSDave Kleikamp handle_t *handle; 146617ba13bSMingming Cao struct ext4_iloc iloc; 147ac27a0ecSDave Kleikamp __u32 generation; 148ac27a0ecSDave Kleikamp int err; 149ac27a0ecSDave Kleikamp 1502e149670SSerge E. Hallyn if (!inode_owner_or_capable(inode)) 151ac27a0ecSDave Kleikamp return -EPERM; 15242a74f20SDave Hansen 15342a74f20SDave Hansen err = mnt_want_write(filp->f_path.mnt); 15442a74f20SDave Hansen if (err) 15542a74f20SDave Hansen return err; 15642a74f20SDave Hansen if (get_user(generation, (int __user *) arg)) { 15742a74f20SDave Hansen err = -EFAULT; 15842a74f20SDave Hansen goto setversion_out; 15942a74f20SDave Hansen } 160ac27a0ecSDave Kleikamp 161617ba13bSMingming Cao handle = ext4_journal_start(inode, 1); 16242a74f20SDave Hansen if (IS_ERR(handle)) { 16342a74f20SDave Hansen err = PTR_ERR(handle); 16442a74f20SDave Hansen goto setversion_out; 16542a74f20SDave Hansen } 166617ba13bSMingming Cao err = ext4_reserve_inode_write(handle, inode, &iloc); 167ac27a0ecSDave Kleikamp if (err == 0) { 168ef7f3835SKalpak Shah inode->i_ctime = ext4_current_time(inode); 169ac27a0ecSDave Kleikamp inode->i_generation = generation; 170617ba13bSMingming Cao err = ext4_mark_iloc_dirty(handle, inode, &iloc); 171ac27a0ecSDave Kleikamp } 172617ba13bSMingming Cao ext4_journal_stop(handle); 17342a74f20SDave Hansen setversion_out: 17442a74f20SDave Hansen mnt_drop_write(filp->f_path.mnt); 175ac27a0ecSDave Kleikamp return err; 176ac27a0ecSDave Kleikamp } 177e23291b9SJose R. Santos #ifdef CONFIG_JBD2_DEBUG 178617ba13bSMingming Cao case EXT4_IOC_WAIT_FOR_READONLY: 179ac27a0ecSDave Kleikamp /* 180ac27a0ecSDave Kleikamp * This is racy - by the time we're woken up and running, 181ac27a0ecSDave Kleikamp * the superblock could be released. And the module could 182ac27a0ecSDave Kleikamp * have been unloaded. So sue me. 183ac27a0ecSDave Kleikamp * 184ac27a0ecSDave Kleikamp * Returns 1 if it slept, else zero. 185ac27a0ecSDave Kleikamp */ 186ac27a0ecSDave Kleikamp { 187ac27a0ecSDave Kleikamp DECLARE_WAITQUEUE(wait, current); 188ac27a0ecSDave Kleikamp int ret = 0; 189ac27a0ecSDave Kleikamp 190ac27a0ecSDave Kleikamp set_current_state(TASK_INTERRUPTIBLE); 191617ba13bSMingming Cao add_wait_queue(&EXT4_SB(sb)->ro_wait_queue, &wait); 192617ba13bSMingming Cao if (timer_pending(&EXT4_SB(sb)->turn_ro_timer)) { 193ac27a0ecSDave Kleikamp schedule(); 194ac27a0ecSDave Kleikamp ret = 1; 195ac27a0ecSDave Kleikamp } 196617ba13bSMingming Cao remove_wait_queue(&EXT4_SB(sb)->ro_wait_queue, &wait); 197ac27a0ecSDave Kleikamp return ret; 198ac27a0ecSDave Kleikamp } 199ac27a0ecSDave Kleikamp #endif 200617ba13bSMingming Cao case EXT4_IOC_GROUP_EXTEND: { 201617ba13bSMingming Cao ext4_fsblk_t n_blocks_count; 202ac046f1dSPeng Tao int err, err2=0; 203ac27a0ecSDave Kleikamp 2048f82f840SYongqiang Yang err = ext4_resize_begin(sb); 2058f82f840SYongqiang Yang if (err) 2068f82f840SYongqiang Yang return err; 207ac27a0ecSDave Kleikamp 208ac27a0ecSDave Kleikamp if (get_user(n_blocks_count, (__u32 __user *)arg)) 209ac27a0ecSDave Kleikamp return -EFAULT; 210ac27a0ecSDave Kleikamp 211bab08ab9STheodore Ts'o if (EXT4_HAS_RO_COMPAT_FEATURE(sb, 212bab08ab9STheodore Ts'o EXT4_FEATURE_RO_COMPAT_BIGALLOC)) { 213bab08ab9STheodore Ts'o ext4_msg(sb, KERN_ERR, 214bab08ab9STheodore Ts'o "Online resizing not supported with bigalloc"); 215bab08ab9STheodore Ts'o return -EOPNOTSUPP; 216bab08ab9STheodore Ts'o } 217bab08ab9STheodore Ts'o 21842a74f20SDave Hansen err = mnt_want_write(filp->f_path.mnt); 21942a74f20SDave Hansen if (err) 22042a74f20SDave Hansen return err; 22142a74f20SDave Hansen 222617ba13bSMingming Cao err = ext4_group_extend(sb, EXT4_SB(sb)->s_es, n_blocks_count); 223ac046f1dSPeng Tao if (EXT4_SB(sb)->s_journal) { 224dab291afSMingming Cao jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); 2257ffe1ea8SHidehiro Kawai err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal); 226dab291afSMingming Cao jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); 227ac046f1dSPeng Tao } 2287ffe1ea8SHidehiro Kawai if (err == 0) 2297ffe1ea8SHidehiro Kawai err = err2; 23042a74f20SDave Hansen mnt_drop_write(filp->f_path.mnt); 2318f82f840SYongqiang Yang ext4_resize_end(sb); 232ac27a0ecSDave Kleikamp 233ac27a0ecSDave Kleikamp return err; 234ac27a0ecSDave Kleikamp } 235748de673SAkira Fujita 236748de673SAkira Fujita case EXT4_IOC_MOVE_EXT: { 237748de673SAkira Fujita struct move_extent me; 238748de673SAkira Fujita struct file *donor_filp; 239748de673SAkira Fujita int err; 240748de673SAkira Fujita 2414a58579bSAkira Fujita if (!(filp->f_mode & FMODE_READ) || 2424a58579bSAkira Fujita !(filp->f_mode & FMODE_WRITE)) 2434a58579bSAkira Fujita return -EBADF; 2444a58579bSAkira Fujita 245748de673SAkira Fujita if (copy_from_user(&me, 246748de673SAkira Fujita (struct move_extent __user *)arg, sizeof(me))) 247748de673SAkira Fujita return -EFAULT; 2484a58579bSAkira Fujita me.moved_len = 0; 249748de673SAkira Fujita 250748de673SAkira Fujita donor_filp = fget(me.donor_fd); 251748de673SAkira Fujita if (!donor_filp) 252748de673SAkira Fujita return -EBADF; 253748de673SAkira Fujita 2544a58579bSAkira Fujita if (!(donor_filp->f_mode & FMODE_WRITE)) { 2554a58579bSAkira Fujita err = -EBADF; 2564a58579bSAkira Fujita goto mext_out; 257748de673SAkira Fujita } 258748de673SAkira Fujita 259bab08ab9STheodore Ts'o if (EXT4_HAS_RO_COMPAT_FEATURE(sb, 260bab08ab9STheodore Ts'o EXT4_FEATURE_RO_COMPAT_BIGALLOC)) { 261bab08ab9STheodore Ts'o ext4_msg(sb, KERN_ERR, 262bab08ab9STheodore Ts'o "Online defrag not supported with bigalloc"); 263bab08ab9STheodore Ts'o return -EOPNOTSUPP; 264bab08ab9STheodore Ts'o } 265bab08ab9STheodore Ts'o 2664a58579bSAkira Fujita err = mnt_want_write(filp->f_path.mnt); 2674a58579bSAkira Fujita if (err) 2684a58579bSAkira Fujita goto mext_out; 2694a58579bSAkira Fujita 270748de673SAkira Fujita err = ext4_move_extents(filp, donor_filp, me.orig_start, 271748de673SAkira Fujita me.donor_start, me.len, &me.moved_len); 2724a58579bSAkira Fujita mnt_drop_write(filp->f_path.mnt); 2734a58579bSAkira Fujita if (me.moved_len > 0) 2744a58579bSAkira Fujita file_remove_suid(donor_filp); 275748de673SAkira Fujita 276c437b273SAkira Fujita if (copy_to_user((struct move_extent __user *)arg, 277c437b273SAkira Fujita &me, sizeof(me))) 2784a58579bSAkira Fujita err = -EFAULT; 2794a58579bSAkira Fujita mext_out: 2804a58579bSAkira Fujita fput(donor_filp); 281748de673SAkira Fujita return err; 282748de673SAkira Fujita } 283748de673SAkira Fujita 284617ba13bSMingming Cao case EXT4_IOC_GROUP_ADD: { 285617ba13bSMingming Cao struct ext4_new_group_data input; 286ac046f1dSPeng Tao int err, err2=0; 287ac27a0ecSDave Kleikamp 2888f82f840SYongqiang Yang err = ext4_resize_begin(sb); 2898f82f840SYongqiang Yang if (err) 2908f82f840SYongqiang Yang return err; 291ac27a0ecSDave Kleikamp 292617ba13bSMingming Cao if (copy_from_user(&input, (struct ext4_new_group_input __user *)arg, 293ac27a0ecSDave Kleikamp sizeof(input))) 294ac27a0ecSDave Kleikamp return -EFAULT; 295ac27a0ecSDave Kleikamp 296bab08ab9STheodore Ts'o if (EXT4_HAS_RO_COMPAT_FEATURE(sb, 297bab08ab9STheodore Ts'o EXT4_FEATURE_RO_COMPAT_BIGALLOC)) { 298bab08ab9STheodore Ts'o ext4_msg(sb, KERN_ERR, 299bab08ab9STheodore Ts'o "Online resizing not supported with bigalloc"); 300bab08ab9STheodore Ts'o return -EOPNOTSUPP; 301bab08ab9STheodore Ts'o } 302bab08ab9STheodore Ts'o 30342a74f20SDave Hansen err = mnt_want_write(filp->f_path.mnt); 30442a74f20SDave Hansen if (err) 30542a74f20SDave Hansen return err; 30642a74f20SDave Hansen 307617ba13bSMingming Cao err = ext4_group_add(sb, &input); 308ac046f1dSPeng Tao if (EXT4_SB(sb)->s_journal) { 309dab291afSMingming Cao jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); 3107ffe1ea8SHidehiro Kawai err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal); 311dab291afSMingming Cao jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); 312ac046f1dSPeng Tao } 3137ffe1ea8SHidehiro Kawai if (err == 0) 3147ffe1ea8SHidehiro Kawai err = err2; 31542a74f20SDave Hansen mnt_drop_write(filp->f_path.mnt); 3168f82f840SYongqiang Yang ext4_resize_end(sb); 317ac27a0ecSDave Kleikamp 318ac27a0ecSDave Kleikamp return err; 319ac27a0ecSDave Kleikamp } 320ac27a0ecSDave Kleikamp 321c14c6fd5SAneesh Kumar K.V case EXT4_IOC_MIGRATE: 3222a43a878SAneesh Kumar K.V { 3232a43a878SAneesh Kumar K.V int err; 3242e149670SSerge E. Hallyn if (!inode_owner_or_capable(inode)) 3252a43a878SAneesh Kumar K.V return -EACCES; 3262a43a878SAneesh Kumar K.V 3272a43a878SAneesh Kumar K.V err = mnt_want_write(filp->f_path.mnt); 3282a43a878SAneesh Kumar K.V if (err) 3292a43a878SAneesh Kumar K.V return err; 3302a43a878SAneesh Kumar K.V /* 3312a43a878SAneesh Kumar K.V * inode_mutex prevent write and truncate on the file. 3322a43a878SAneesh Kumar K.V * Read still goes through. We take i_data_sem in 3332a43a878SAneesh Kumar K.V * ext4_ext_swap_inode_data before we switch the 3342a43a878SAneesh Kumar K.V * inode format to prevent read. 3352a43a878SAneesh Kumar K.V */ 3362a43a878SAneesh Kumar K.V mutex_lock(&(inode->i_mutex)); 3372a43a878SAneesh Kumar K.V err = ext4_ext_migrate(inode); 3382a43a878SAneesh Kumar K.V mutex_unlock(&(inode->i_mutex)); 3392a43a878SAneesh Kumar K.V mnt_drop_write(filp->f_path.mnt); 3402a43a878SAneesh Kumar K.V return err; 3412a43a878SAneesh Kumar K.V } 342c14c6fd5SAneesh Kumar K.V 343ccd2506bSTheodore Ts'o case EXT4_IOC_ALLOC_DA_BLKS: 344ccd2506bSTheodore Ts'o { 345ccd2506bSTheodore Ts'o int err; 3462e149670SSerge E. Hallyn if (!inode_owner_or_capable(inode)) 347ccd2506bSTheodore Ts'o return -EACCES; 348ccd2506bSTheodore Ts'o 349ccd2506bSTheodore Ts'o err = mnt_want_write(filp->f_path.mnt); 350ccd2506bSTheodore Ts'o if (err) 351ccd2506bSTheodore Ts'o return err; 352ccd2506bSTheodore Ts'o err = ext4_alloc_da_blocks(inode); 353ccd2506bSTheodore Ts'o mnt_drop_write(filp->f_path.mnt); 354ccd2506bSTheodore Ts'o return err; 355ccd2506bSTheodore Ts'o } 356ccd2506bSTheodore Ts'o 357e681c047SLukas Czerner case FITRIM: 358e681c047SLukas Czerner { 35941431792SLukas Czerner struct request_queue *q = bdev_get_queue(sb->s_bdev); 360e681c047SLukas Czerner struct fstrim_range range; 361e681c047SLukas Czerner int ret = 0; 362e681c047SLukas Czerner 363e681c047SLukas Czerner if (!capable(CAP_SYS_ADMIN)) 364e681c047SLukas Czerner return -EPERM; 365e681c047SLukas Czerner 36641431792SLukas Czerner if (!blk_queue_discard(q)) 36741431792SLukas Czerner return -EOPNOTSUPP; 36841431792SLukas Czerner 369bab08ab9STheodore Ts'o if (EXT4_HAS_RO_COMPAT_FEATURE(sb, 370bab08ab9STheodore Ts'o EXT4_FEATURE_RO_COMPAT_BIGALLOC)) { 371bab08ab9STheodore Ts'o ext4_msg(sb, KERN_ERR, 372bab08ab9STheodore Ts'o "FITRIM not supported with bigalloc"); 373bab08ab9STheodore Ts'o return -EOPNOTSUPP; 374bab08ab9STheodore Ts'o } 375bab08ab9STheodore Ts'o 376e681c047SLukas Czerner if (copy_from_user(&range, (struct fstrim_range *)arg, 377e681c047SLukas Czerner sizeof(range))) 378e681c047SLukas Czerner return -EFAULT; 379e681c047SLukas Czerner 3805c2ed62fSLukas Czerner range.minlen = max((unsigned int)range.minlen, 3815c2ed62fSLukas Czerner q->limits.discard_granularity); 382e681c047SLukas Czerner ret = ext4_trim_fs(sb, &range); 383e681c047SLukas Czerner if (ret < 0) 384e681c047SLukas Czerner return ret; 385e681c047SLukas Czerner 386e681c047SLukas Czerner if (copy_to_user((struct fstrim_range *)arg, &range, 387e681c047SLukas Czerner sizeof(range))) 388e681c047SLukas Czerner return -EFAULT; 389e681c047SLukas Czerner 390e681c047SLukas Czerner return 0; 391e681c047SLukas Czerner } 392e681c047SLukas Czerner 393ac27a0ecSDave Kleikamp default: 394ac27a0ecSDave Kleikamp return -ENOTTY; 395ac27a0ecSDave Kleikamp } 396ac27a0ecSDave Kleikamp } 397ac27a0ecSDave Kleikamp 398ac27a0ecSDave Kleikamp #ifdef CONFIG_COMPAT 399617ba13bSMingming Cao long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 400ac27a0ecSDave Kleikamp { 401ac27a0ecSDave Kleikamp /* These are just misnamed, they actually get/put from/to user an int */ 402ac27a0ecSDave Kleikamp switch (cmd) { 403617ba13bSMingming Cao case EXT4_IOC32_GETFLAGS: 404617ba13bSMingming Cao cmd = EXT4_IOC_GETFLAGS; 405ac27a0ecSDave Kleikamp break; 406617ba13bSMingming Cao case EXT4_IOC32_SETFLAGS: 407617ba13bSMingming Cao cmd = EXT4_IOC_SETFLAGS; 408ac27a0ecSDave Kleikamp break; 409617ba13bSMingming Cao case EXT4_IOC32_GETVERSION: 410617ba13bSMingming Cao cmd = EXT4_IOC_GETVERSION; 411ac27a0ecSDave Kleikamp break; 412617ba13bSMingming Cao case EXT4_IOC32_SETVERSION: 413617ba13bSMingming Cao cmd = EXT4_IOC_SETVERSION; 414ac27a0ecSDave Kleikamp break; 415617ba13bSMingming Cao case EXT4_IOC32_GROUP_EXTEND: 416617ba13bSMingming Cao cmd = EXT4_IOC_GROUP_EXTEND; 417ac27a0ecSDave Kleikamp break; 418617ba13bSMingming Cao case EXT4_IOC32_GETVERSION_OLD: 419617ba13bSMingming Cao cmd = EXT4_IOC_GETVERSION_OLD; 420ac27a0ecSDave Kleikamp break; 421617ba13bSMingming Cao case EXT4_IOC32_SETVERSION_OLD: 422617ba13bSMingming Cao cmd = EXT4_IOC_SETVERSION_OLD; 423ac27a0ecSDave Kleikamp break; 424e23291b9SJose R. Santos #ifdef CONFIG_JBD2_DEBUG 425617ba13bSMingming Cao case EXT4_IOC32_WAIT_FOR_READONLY: 426617ba13bSMingming Cao cmd = EXT4_IOC_WAIT_FOR_READONLY; 427ac27a0ecSDave Kleikamp break; 428ac27a0ecSDave Kleikamp #endif 429617ba13bSMingming Cao case EXT4_IOC32_GETRSVSZ: 430617ba13bSMingming Cao cmd = EXT4_IOC_GETRSVSZ; 431ac27a0ecSDave Kleikamp break; 432617ba13bSMingming Cao case EXT4_IOC32_SETRSVSZ: 433617ba13bSMingming Cao cmd = EXT4_IOC_SETRSVSZ; 434ac27a0ecSDave Kleikamp break; 4354d92dc0fSBen Hutchings case EXT4_IOC32_GROUP_ADD: { 4364d92dc0fSBen Hutchings struct compat_ext4_new_group_input __user *uinput; 4374d92dc0fSBen Hutchings struct ext4_new_group_input input; 4384d92dc0fSBen Hutchings mm_segment_t old_fs; 4394d92dc0fSBen Hutchings int err; 4404d92dc0fSBen Hutchings 4414d92dc0fSBen Hutchings uinput = compat_ptr(arg); 4424d92dc0fSBen Hutchings err = get_user(input.group, &uinput->group); 4434d92dc0fSBen Hutchings err |= get_user(input.block_bitmap, &uinput->block_bitmap); 4444d92dc0fSBen Hutchings err |= get_user(input.inode_bitmap, &uinput->inode_bitmap); 4454d92dc0fSBen Hutchings err |= get_user(input.inode_table, &uinput->inode_table); 4464d92dc0fSBen Hutchings err |= get_user(input.blocks_count, &uinput->blocks_count); 4474d92dc0fSBen Hutchings err |= get_user(input.reserved_blocks, 4484d92dc0fSBen Hutchings &uinput->reserved_blocks); 4494d92dc0fSBen Hutchings if (err) 4504d92dc0fSBen Hutchings return -EFAULT; 4514d92dc0fSBen Hutchings old_fs = get_fs(); 4524d92dc0fSBen Hutchings set_fs(KERNEL_DS); 4534d92dc0fSBen Hutchings err = ext4_ioctl(file, EXT4_IOC_GROUP_ADD, 4544d92dc0fSBen Hutchings (unsigned long) &input); 4554d92dc0fSBen Hutchings set_fs(old_fs); 4564d92dc0fSBen Hutchings return err; 4574d92dc0fSBen Hutchings } 458b684b2eeSChristian Borntraeger case EXT4_IOC_MOVE_EXT: 459a56e69c2STao Ma case FITRIM: 460b684b2eeSChristian Borntraeger break; 461ac27a0ecSDave Kleikamp default: 462ac27a0ecSDave Kleikamp return -ENOIOCTLCMD; 463ac27a0ecSDave Kleikamp } 4645cdd7b2dSAndi Kleen return ext4_ioctl(file, cmd, (unsigned long) compat_ptr(arg)); 465ac27a0ecSDave Kleikamp } 466ac27a0ecSDave Kleikamp #endif 467