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 2119c5246dSYongqiang Yang #define MAX_32_NUM ((((unsigned long long) 1) << 32) - 1) 2219c5246dSYongqiang Yang 235cdd7b2dSAndi Kleen long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 24ac27a0ecSDave Kleikamp { 255cdd7b2dSAndi Kleen struct inode *inode = filp->f_dentry->d_inode; 26bab08ab9STheodore Ts'o struct super_block *sb = inode->i_sb; 27617ba13bSMingming Cao struct ext4_inode_info *ei = EXT4_I(inode); 28ac27a0ecSDave Kleikamp unsigned int flags; 29ac27a0ecSDave Kleikamp 30617ba13bSMingming Cao ext4_debug("cmd = %u, arg = %lu\n", cmd, arg); 31ac27a0ecSDave Kleikamp 32ac27a0ecSDave Kleikamp switch (cmd) { 33617ba13bSMingming Cao case EXT4_IOC_GETFLAGS: 34ff9ddf7eSJan Kara ext4_get_inode_flags(ei); 35617ba13bSMingming Cao flags = ei->i_flags & EXT4_FL_USER_VISIBLE; 36ac27a0ecSDave Kleikamp return put_user(flags, (int __user *) arg); 37617ba13bSMingming Cao case EXT4_IOC_SETFLAGS: { 38ac27a0ecSDave Kleikamp handle_t *handle = NULL; 394db46fc2SAneesh Kumar K.V int err, migrate = 0; 40617ba13bSMingming Cao struct ext4_iloc iloc; 4179906964STheodore Ts'o unsigned int oldflags, mask, i; 42ac27a0ecSDave Kleikamp unsigned int jflag; 43ac27a0ecSDave Kleikamp 442e149670SSerge E. Hallyn if (!inode_owner_or_capable(inode)) 45ac27a0ecSDave Kleikamp return -EACCES; 46ac27a0ecSDave Kleikamp 47ac27a0ecSDave Kleikamp if (get_user(flags, (int __user *) arg)) 48ac27a0ecSDave Kleikamp return -EFAULT; 49ac27a0ecSDave Kleikamp 50a561be71SAl Viro err = mnt_want_write_file(filp); 5142a74f20SDave Hansen if (err) 5242a74f20SDave Hansen return err; 5342a74f20SDave Hansen 542dc6b0d4SDuane Griffin flags = ext4_mask_flags(inode->i_mode, flags); 55ac27a0ecSDave Kleikamp 5642a74f20SDave Hansen err = -EPERM; 57ac27a0ecSDave Kleikamp mutex_lock(&inode->i_mutex); 58e47776a0SJan Kara /* Is it quota file? Do not allow user to mess with it */ 5942a74f20SDave Hansen if (IS_NOQUOTA(inode)) 6042a74f20SDave Hansen goto flags_out; 6142a74f20SDave Hansen 62ac27a0ecSDave Kleikamp oldflags = ei->i_flags; 63ac27a0ecSDave Kleikamp 64ac27a0ecSDave Kleikamp /* The JOURNAL_DATA flag is modifiable only by root */ 65617ba13bSMingming Cao jflag = flags & EXT4_JOURNAL_DATA_FL; 66ac27a0ecSDave Kleikamp 67ac27a0ecSDave Kleikamp /* 68ac27a0ecSDave Kleikamp * The IMMUTABLE and APPEND_ONLY flags can only be changed by 69ac27a0ecSDave Kleikamp * the relevant capability. 70ac27a0ecSDave Kleikamp * 71ac27a0ecSDave Kleikamp * This test looks nicer. Thanks to Pauline Middelink 72ac27a0ecSDave Kleikamp */ 73617ba13bSMingming Cao if ((flags ^ oldflags) & (EXT4_APPEND_FL | EXT4_IMMUTABLE_FL)) { 7442a74f20SDave Hansen if (!capable(CAP_LINUX_IMMUTABLE)) 7542a74f20SDave Hansen goto flags_out; 76ac27a0ecSDave Kleikamp } 77ac27a0ecSDave Kleikamp 78ac27a0ecSDave Kleikamp /* 79ac27a0ecSDave Kleikamp * The JOURNAL_DATA flag can only be changed by 80ac27a0ecSDave Kleikamp * the relevant capability. 81ac27a0ecSDave Kleikamp */ 82617ba13bSMingming Cao if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) { 8342a74f20SDave Hansen if (!capable(CAP_SYS_RESOURCE)) 8442a74f20SDave Hansen goto flags_out; 85ac27a0ecSDave Kleikamp } 864db46fc2SAneesh Kumar K.V if (oldflags & EXT4_EXTENTS_FL) { 874db46fc2SAneesh Kumar K.V /* We don't support clearning extent flags */ 884db46fc2SAneesh Kumar K.V if (!(flags & EXT4_EXTENTS_FL)) { 894db46fc2SAneesh Kumar K.V err = -EOPNOTSUPP; 904db46fc2SAneesh Kumar K.V goto flags_out; 914db46fc2SAneesh Kumar K.V } 924db46fc2SAneesh Kumar K.V } else if (flags & EXT4_EXTENTS_FL) { 934db46fc2SAneesh Kumar K.V /* migrate the file */ 944db46fc2SAneesh Kumar K.V migrate = 1; 954db46fc2SAneesh Kumar K.V flags &= ~EXT4_EXTENTS_FL; 964db46fc2SAneesh Kumar K.V } 97ac27a0ecSDave Kleikamp 98c8d46e41SJiaying Zhang if (flags & EXT4_EOFBLOCKS_FL) { 99c8d46e41SJiaying Zhang /* we don't support adding EOFBLOCKS flag */ 100c8d46e41SJiaying Zhang if (!(oldflags & EXT4_EOFBLOCKS_FL)) { 101c8d46e41SJiaying Zhang err = -EOPNOTSUPP; 102c8d46e41SJiaying Zhang goto flags_out; 103c8d46e41SJiaying Zhang } 104c8d46e41SJiaying Zhang } else if (oldflags & EXT4_EOFBLOCKS_FL) 105c8d46e41SJiaying Zhang ext4_truncate(inode); 106c8d46e41SJiaying Zhang 107617ba13bSMingming Cao handle = ext4_journal_start(inode, 1); 108ac27a0ecSDave Kleikamp if (IS_ERR(handle)) { 10942a74f20SDave Hansen err = PTR_ERR(handle); 11042a74f20SDave Hansen goto flags_out; 111ac27a0ecSDave Kleikamp } 112ac27a0ecSDave Kleikamp if (IS_SYNC(inode)) 1130390131bSFrank Mayhar ext4_handle_sync(handle); 114617ba13bSMingming Cao err = ext4_reserve_inode_write(handle, inode, &iloc); 115ac27a0ecSDave Kleikamp if (err) 116ac27a0ecSDave Kleikamp goto flags_err; 117ac27a0ecSDave Kleikamp 11879906964STheodore Ts'o for (i = 0, mask = 1; i < 32; i++, mask <<= 1) { 11979906964STheodore Ts'o if (!(mask & EXT4_FL_USER_MODIFIABLE)) 12079906964STheodore Ts'o continue; 12179906964STheodore Ts'o if (mask & flags) 12279906964STheodore Ts'o ext4_set_inode_flag(inode, i); 12379906964STheodore Ts'o else 12479906964STheodore Ts'o ext4_clear_inode_flag(inode, i); 12579906964STheodore Ts'o } 126ac27a0ecSDave Kleikamp ei->i_flags = flags; 127ac27a0ecSDave Kleikamp 128617ba13bSMingming Cao ext4_set_inode_flags(inode); 129ef7f3835SKalpak Shah inode->i_ctime = ext4_current_time(inode); 130ac27a0ecSDave Kleikamp 131617ba13bSMingming Cao err = ext4_mark_iloc_dirty(handle, inode, &iloc); 132ac27a0ecSDave Kleikamp flags_err: 133617ba13bSMingming Cao ext4_journal_stop(handle); 13442a74f20SDave Hansen if (err) 13542a74f20SDave Hansen goto flags_out; 136ac27a0ecSDave Kleikamp 137617ba13bSMingming Cao if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) 138617ba13bSMingming Cao err = ext4_change_inode_journal_flag(inode, jflag); 1394db46fc2SAneesh Kumar K.V if (err) 1404db46fc2SAneesh Kumar K.V goto flags_out; 1414db46fc2SAneesh Kumar K.V if (migrate) 1424db46fc2SAneesh Kumar K.V err = ext4_ext_migrate(inode); 14342a74f20SDave Hansen flags_out: 144ac27a0ecSDave Kleikamp mutex_unlock(&inode->i_mutex); 1452a79f17eSAl Viro mnt_drop_write_file(filp); 146ac27a0ecSDave Kleikamp return err; 147ac27a0ecSDave Kleikamp } 148617ba13bSMingming Cao case EXT4_IOC_GETVERSION: 149617ba13bSMingming Cao case EXT4_IOC_GETVERSION_OLD: 150ac27a0ecSDave Kleikamp return put_user(inode->i_generation, (int __user *) arg); 151617ba13bSMingming Cao case EXT4_IOC_SETVERSION: 152617ba13bSMingming Cao case EXT4_IOC_SETVERSION_OLD: { 153ac27a0ecSDave Kleikamp handle_t *handle; 154617ba13bSMingming Cao struct ext4_iloc iloc; 155ac27a0ecSDave Kleikamp __u32 generation; 156ac27a0ecSDave Kleikamp int err; 157ac27a0ecSDave Kleikamp 1582e149670SSerge E. Hallyn if (!inode_owner_or_capable(inode)) 159ac27a0ecSDave Kleikamp return -EPERM; 16042a74f20SDave Hansen 161814525f4SDarrick J. Wong if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, 162814525f4SDarrick J. Wong EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) { 163814525f4SDarrick J. Wong ext4_warning(sb, "Setting inode version is not " 164814525f4SDarrick J. Wong "supported with metadata_csum enabled."); 165814525f4SDarrick J. Wong return -ENOTTY; 166814525f4SDarrick J. Wong } 167814525f4SDarrick J. Wong 168a561be71SAl Viro err = mnt_want_write_file(filp); 16942a74f20SDave Hansen if (err) 17042a74f20SDave Hansen return err; 17142a74f20SDave Hansen if (get_user(generation, (int __user *) arg)) { 17242a74f20SDave Hansen err = -EFAULT; 17342a74f20SDave Hansen goto setversion_out; 17442a74f20SDave Hansen } 175ac27a0ecSDave Kleikamp 1766c2155b9SDjalal Harouni mutex_lock(&inode->i_mutex); 177617ba13bSMingming Cao handle = ext4_journal_start(inode, 1); 17842a74f20SDave Hansen if (IS_ERR(handle)) { 17942a74f20SDave Hansen err = PTR_ERR(handle); 1806c2155b9SDjalal Harouni goto unlock_out; 18142a74f20SDave Hansen } 182617ba13bSMingming Cao err = ext4_reserve_inode_write(handle, inode, &iloc); 183ac27a0ecSDave Kleikamp if (err == 0) { 184ef7f3835SKalpak Shah inode->i_ctime = ext4_current_time(inode); 185ac27a0ecSDave Kleikamp inode->i_generation = generation; 186617ba13bSMingming Cao err = ext4_mark_iloc_dirty(handle, inode, &iloc); 187ac27a0ecSDave Kleikamp } 188617ba13bSMingming Cao ext4_journal_stop(handle); 1896c2155b9SDjalal Harouni 1906c2155b9SDjalal Harouni unlock_out: 1916c2155b9SDjalal Harouni mutex_unlock(&inode->i_mutex); 19242a74f20SDave Hansen setversion_out: 1932a79f17eSAl Viro mnt_drop_write_file(filp); 194ac27a0ecSDave Kleikamp return err; 195ac27a0ecSDave Kleikamp } 196617ba13bSMingming Cao case EXT4_IOC_GROUP_EXTEND: { 197617ba13bSMingming Cao ext4_fsblk_t n_blocks_count; 198ac046f1dSPeng Tao int err, err2=0; 199ac27a0ecSDave Kleikamp 2008f82f840SYongqiang Yang err = ext4_resize_begin(sb); 2018f82f840SYongqiang Yang if (err) 2028f82f840SYongqiang Yang return err; 203ac27a0ecSDave Kleikamp 204014a1770SDjalal Harouni if (get_user(n_blocks_count, (__u32 __user *)arg)) { 205014a1770SDjalal Harouni err = -EFAULT; 206014a1770SDjalal Harouni goto group_extend_out; 207014a1770SDjalal Harouni } 208ac27a0ecSDave Kleikamp 209bab08ab9STheodore Ts'o if (EXT4_HAS_RO_COMPAT_FEATURE(sb, 210bab08ab9STheodore Ts'o EXT4_FEATURE_RO_COMPAT_BIGALLOC)) { 211bab08ab9STheodore Ts'o ext4_msg(sb, KERN_ERR, 212bab08ab9STheodore Ts'o "Online resizing not supported with bigalloc"); 213014a1770SDjalal Harouni err = -EOPNOTSUPP; 214014a1770SDjalal Harouni goto group_extend_out; 215bab08ab9STheodore Ts'o } 216bab08ab9STheodore Ts'o 217a561be71SAl Viro err = mnt_want_write_file(filp); 21842a74f20SDave Hansen if (err) 219014a1770SDjalal Harouni goto group_extend_out; 22042a74f20SDave Hansen 221617ba13bSMingming Cao err = ext4_group_extend(sb, EXT4_SB(sb)->s_es, n_blocks_count); 222ac046f1dSPeng Tao if (EXT4_SB(sb)->s_journal) { 223dab291afSMingming Cao jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); 2247ffe1ea8SHidehiro Kawai err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal); 225dab291afSMingming Cao jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); 226ac046f1dSPeng Tao } 2277ffe1ea8SHidehiro Kawai if (err == 0) 2287ffe1ea8SHidehiro Kawai err = err2; 2292a79f17eSAl Viro mnt_drop_write_file(filp); 230014a1770SDjalal Harouni group_extend_out: 2318f82f840SYongqiang Yang ext4_resize_end(sb); 232ac27a0ecSDave Kleikamp return err; 233ac27a0ecSDave Kleikamp } 234748de673SAkira Fujita 235748de673SAkira Fujita case EXT4_IOC_MOVE_EXT: { 236748de673SAkira Fujita struct move_extent me; 237748de673SAkira Fujita struct file *donor_filp; 238748de673SAkira Fujita int err; 239748de673SAkira Fujita 2404a58579bSAkira Fujita if (!(filp->f_mode & FMODE_READ) || 2414a58579bSAkira Fujita !(filp->f_mode & FMODE_WRITE)) 2424a58579bSAkira Fujita return -EBADF; 2434a58579bSAkira Fujita 244748de673SAkira Fujita if (copy_from_user(&me, 245748de673SAkira Fujita (struct move_extent __user *)arg, sizeof(me))) 246748de673SAkira Fujita return -EFAULT; 2474a58579bSAkira Fujita me.moved_len = 0; 248748de673SAkira Fujita 249748de673SAkira Fujita donor_filp = fget(me.donor_fd); 250748de673SAkira Fujita if (!donor_filp) 251748de673SAkira Fujita return -EBADF; 252748de673SAkira Fujita 2534a58579bSAkira Fujita if (!(donor_filp->f_mode & FMODE_WRITE)) { 2544a58579bSAkira Fujita err = -EBADF; 2554a58579bSAkira Fujita goto mext_out; 256748de673SAkira Fujita } 257748de673SAkira Fujita 258bab08ab9STheodore Ts'o if (EXT4_HAS_RO_COMPAT_FEATURE(sb, 259bab08ab9STheodore Ts'o EXT4_FEATURE_RO_COMPAT_BIGALLOC)) { 260bab08ab9STheodore Ts'o ext4_msg(sb, KERN_ERR, 261bab08ab9STheodore Ts'o "Online defrag not supported with bigalloc"); 262bab08ab9STheodore Ts'o return -EOPNOTSUPP; 263bab08ab9STheodore Ts'o } 264bab08ab9STheodore Ts'o 265a561be71SAl Viro err = mnt_want_write_file(filp); 2664a58579bSAkira Fujita if (err) 2674a58579bSAkira Fujita goto mext_out; 2684a58579bSAkira Fujita 269748de673SAkira Fujita err = ext4_move_extents(filp, donor_filp, me.orig_start, 270748de673SAkira Fujita me.donor_start, me.len, &me.moved_len); 2712a79f17eSAl Viro mnt_drop_write_file(filp); 2724a58579bSAkira Fujita mnt_drop_write(filp->f_path.mnt); 273748de673SAkira Fujita 274c437b273SAkira Fujita if (copy_to_user((struct move_extent __user *)arg, 275c437b273SAkira Fujita &me, sizeof(me))) 2764a58579bSAkira Fujita err = -EFAULT; 2774a58579bSAkira Fujita mext_out: 2784a58579bSAkira Fujita fput(donor_filp); 279748de673SAkira Fujita return err; 280748de673SAkira Fujita } 281748de673SAkira Fujita 282617ba13bSMingming Cao case EXT4_IOC_GROUP_ADD: { 283617ba13bSMingming Cao struct ext4_new_group_data input; 284ac046f1dSPeng Tao int err, err2=0; 285ac27a0ecSDave Kleikamp 2868f82f840SYongqiang Yang err = ext4_resize_begin(sb); 2878f82f840SYongqiang Yang if (err) 2888f82f840SYongqiang Yang return err; 289ac27a0ecSDave Kleikamp 290617ba13bSMingming Cao if (copy_from_user(&input, (struct ext4_new_group_input __user *)arg, 291014a1770SDjalal Harouni sizeof(input))) { 292014a1770SDjalal Harouni err = -EFAULT; 293014a1770SDjalal Harouni goto group_add_out; 294014a1770SDjalal Harouni } 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"); 300014a1770SDjalal Harouni err = -EOPNOTSUPP; 301014a1770SDjalal Harouni goto group_add_out; 302bab08ab9STheodore Ts'o } 303bab08ab9STheodore Ts'o 304a561be71SAl Viro err = mnt_want_write_file(filp); 30542a74f20SDave Hansen if (err) 306014a1770SDjalal Harouni goto group_add_out; 30742a74f20SDave Hansen 308617ba13bSMingming Cao err = ext4_group_add(sb, &input); 309ac046f1dSPeng Tao if (EXT4_SB(sb)->s_journal) { 310dab291afSMingming Cao jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); 3117ffe1ea8SHidehiro Kawai err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal); 312dab291afSMingming Cao jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); 313ac046f1dSPeng Tao } 3147ffe1ea8SHidehiro Kawai if (err == 0) 3157ffe1ea8SHidehiro Kawai err = err2; 3162a79f17eSAl Viro mnt_drop_write_file(filp); 317014a1770SDjalal Harouni group_add_out: 3188f82f840SYongqiang Yang ext4_resize_end(sb); 319ac27a0ecSDave Kleikamp return err; 320ac27a0ecSDave Kleikamp } 321ac27a0ecSDave Kleikamp 322c14c6fd5SAneesh Kumar K.V case EXT4_IOC_MIGRATE: 3232a43a878SAneesh Kumar K.V { 3242a43a878SAneesh Kumar K.V int err; 3252e149670SSerge E. Hallyn if (!inode_owner_or_capable(inode)) 3262a43a878SAneesh Kumar K.V return -EACCES; 3272a43a878SAneesh Kumar K.V 328a561be71SAl Viro err = mnt_want_write_file(filp); 3292a43a878SAneesh Kumar K.V if (err) 3302a43a878SAneesh Kumar K.V return err; 3312a43a878SAneesh Kumar K.V /* 3322a43a878SAneesh Kumar K.V * inode_mutex prevent write and truncate on the file. 3332a43a878SAneesh Kumar K.V * Read still goes through. We take i_data_sem in 3342a43a878SAneesh Kumar K.V * ext4_ext_swap_inode_data before we switch the 3352a43a878SAneesh Kumar K.V * inode format to prevent read. 3362a43a878SAneesh Kumar K.V */ 3372a43a878SAneesh Kumar K.V mutex_lock(&(inode->i_mutex)); 3382a43a878SAneesh Kumar K.V err = ext4_ext_migrate(inode); 3392a43a878SAneesh Kumar K.V mutex_unlock(&(inode->i_mutex)); 3402a79f17eSAl Viro mnt_drop_write_file(filp); 3412a43a878SAneesh Kumar K.V return err; 3422a43a878SAneesh Kumar K.V } 343c14c6fd5SAneesh Kumar K.V 344ccd2506bSTheodore Ts'o case EXT4_IOC_ALLOC_DA_BLKS: 345ccd2506bSTheodore Ts'o { 346ccd2506bSTheodore Ts'o int err; 3472e149670SSerge E. Hallyn if (!inode_owner_or_capable(inode)) 348ccd2506bSTheodore Ts'o return -EACCES; 349ccd2506bSTheodore Ts'o 350a561be71SAl Viro err = mnt_want_write_file(filp); 351ccd2506bSTheodore Ts'o if (err) 352ccd2506bSTheodore Ts'o return err; 353ccd2506bSTheodore Ts'o err = ext4_alloc_da_blocks(inode); 3542a79f17eSAl Viro mnt_drop_write_file(filp); 355ccd2506bSTheodore Ts'o return err; 356ccd2506bSTheodore Ts'o } 357ccd2506bSTheodore Ts'o 35819c5246dSYongqiang Yang case EXT4_IOC_RESIZE_FS: { 35919c5246dSYongqiang Yang ext4_fsblk_t n_blocks_count; 36019c5246dSYongqiang Yang struct super_block *sb = inode->i_sb; 36119c5246dSYongqiang Yang int err = 0, err2 = 0; 36219c5246dSYongqiang Yang 36319c5246dSYongqiang Yang if (EXT4_HAS_RO_COMPAT_FEATURE(sb, 36419c5246dSYongqiang Yang EXT4_FEATURE_RO_COMPAT_BIGALLOC)) { 36519c5246dSYongqiang Yang ext4_msg(sb, KERN_ERR, 36619c5246dSYongqiang Yang "Online resizing not (yet) supported with bigalloc"); 36719c5246dSYongqiang Yang return -EOPNOTSUPP; 36819c5246dSYongqiang Yang } 36919c5246dSYongqiang Yang 37019c5246dSYongqiang Yang if (EXT4_HAS_INCOMPAT_FEATURE(sb, 37119c5246dSYongqiang Yang EXT4_FEATURE_INCOMPAT_META_BG)) { 37219c5246dSYongqiang Yang ext4_msg(sb, KERN_ERR, 37319c5246dSYongqiang Yang "Online resizing not (yet) supported with meta_bg"); 37419c5246dSYongqiang Yang return -EOPNOTSUPP; 37519c5246dSYongqiang Yang } 37619c5246dSYongqiang Yang 37719c5246dSYongqiang Yang if (copy_from_user(&n_blocks_count, (__u64 __user *)arg, 37819c5246dSYongqiang Yang sizeof(__u64))) { 37919c5246dSYongqiang Yang return -EFAULT; 38019c5246dSYongqiang Yang } 38119c5246dSYongqiang Yang 38219c5246dSYongqiang Yang if (n_blocks_count > MAX_32_NUM && 38319c5246dSYongqiang Yang !EXT4_HAS_INCOMPAT_FEATURE(sb, 38419c5246dSYongqiang Yang EXT4_FEATURE_INCOMPAT_64BIT)) { 38519c5246dSYongqiang Yang ext4_msg(sb, KERN_ERR, 38619c5246dSYongqiang Yang "File system only supports 32-bit block numbers"); 38719c5246dSYongqiang Yang return -EOPNOTSUPP; 38819c5246dSYongqiang Yang } 38919c5246dSYongqiang Yang 39019c5246dSYongqiang Yang err = ext4_resize_begin(sb); 39119c5246dSYongqiang Yang if (err) 39219c5246dSYongqiang Yang return err; 39319c5246dSYongqiang Yang 39419c5246dSYongqiang Yang err = mnt_want_write(filp->f_path.mnt); 39519c5246dSYongqiang Yang if (err) 39619c5246dSYongqiang Yang goto resizefs_out; 39719c5246dSYongqiang Yang 39819c5246dSYongqiang Yang err = ext4_resize_fs(sb, n_blocks_count); 39919c5246dSYongqiang Yang if (EXT4_SB(sb)->s_journal) { 40019c5246dSYongqiang Yang jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); 40119c5246dSYongqiang Yang err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal); 40219c5246dSYongqiang Yang jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); 40319c5246dSYongqiang Yang } 40419c5246dSYongqiang Yang if (err == 0) 40519c5246dSYongqiang Yang err = err2; 40619c5246dSYongqiang Yang mnt_drop_write(filp->f_path.mnt); 40719c5246dSYongqiang Yang resizefs_out: 40819c5246dSYongqiang Yang ext4_resize_end(sb); 40919c5246dSYongqiang Yang return err; 41019c5246dSYongqiang Yang } 41119c5246dSYongqiang Yang 412e681c047SLukas Czerner case FITRIM: 413e681c047SLukas Czerner { 41441431792SLukas Czerner struct request_queue *q = bdev_get_queue(sb->s_bdev); 415e681c047SLukas Czerner struct fstrim_range range; 416e681c047SLukas Czerner int ret = 0; 417e681c047SLukas Czerner 418e681c047SLukas Czerner if (!capable(CAP_SYS_ADMIN)) 419e681c047SLukas Czerner return -EPERM; 420e681c047SLukas Czerner 42141431792SLukas Czerner if (!blk_queue_discard(q)) 42241431792SLukas Czerner return -EOPNOTSUPP; 42341431792SLukas Czerner 424bab08ab9STheodore Ts'o if (EXT4_HAS_RO_COMPAT_FEATURE(sb, 425bab08ab9STheodore Ts'o EXT4_FEATURE_RO_COMPAT_BIGALLOC)) { 426bab08ab9STheodore Ts'o ext4_msg(sb, KERN_ERR, 427bab08ab9STheodore Ts'o "FITRIM not supported with bigalloc"); 428bab08ab9STheodore Ts'o return -EOPNOTSUPP; 429bab08ab9STheodore Ts'o } 430bab08ab9STheodore Ts'o 431e6705f7cSH Hartley Sweeten if (copy_from_user(&range, (struct fstrim_range __user *)arg, 432e681c047SLukas Czerner sizeof(range))) 433e681c047SLukas Czerner return -EFAULT; 434e681c047SLukas Czerner 4355c2ed62fSLukas Czerner range.minlen = max((unsigned int)range.minlen, 4365c2ed62fSLukas Czerner q->limits.discard_granularity); 437e681c047SLukas Czerner ret = ext4_trim_fs(sb, &range); 438e681c047SLukas Czerner if (ret < 0) 439e681c047SLukas Czerner return ret; 440e681c047SLukas Czerner 441e6705f7cSH Hartley Sweeten if (copy_to_user((struct fstrim_range __user *)arg, &range, 442e681c047SLukas Czerner sizeof(range))) 443e681c047SLukas Czerner return -EFAULT; 444e681c047SLukas Czerner 445e681c047SLukas Czerner return 0; 446e681c047SLukas Czerner } 447e681c047SLukas Czerner 448ac27a0ecSDave Kleikamp default: 449ac27a0ecSDave Kleikamp return -ENOTTY; 450ac27a0ecSDave Kleikamp } 451ac27a0ecSDave Kleikamp } 452ac27a0ecSDave Kleikamp 453ac27a0ecSDave Kleikamp #ifdef CONFIG_COMPAT 454617ba13bSMingming Cao long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 455ac27a0ecSDave Kleikamp { 456ac27a0ecSDave Kleikamp /* These are just misnamed, they actually get/put from/to user an int */ 457ac27a0ecSDave Kleikamp switch (cmd) { 458617ba13bSMingming Cao case EXT4_IOC32_GETFLAGS: 459617ba13bSMingming Cao cmd = EXT4_IOC_GETFLAGS; 460ac27a0ecSDave Kleikamp break; 461617ba13bSMingming Cao case EXT4_IOC32_SETFLAGS: 462617ba13bSMingming Cao cmd = EXT4_IOC_SETFLAGS; 463ac27a0ecSDave Kleikamp break; 464617ba13bSMingming Cao case EXT4_IOC32_GETVERSION: 465617ba13bSMingming Cao cmd = EXT4_IOC_GETVERSION; 466ac27a0ecSDave Kleikamp break; 467617ba13bSMingming Cao case EXT4_IOC32_SETVERSION: 468617ba13bSMingming Cao cmd = EXT4_IOC_SETVERSION; 469ac27a0ecSDave Kleikamp break; 470617ba13bSMingming Cao case EXT4_IOC32_GROUP_EXTEND: 471617ba13bSMingming Cao cmd = EXT4_IOC_GROUP_EXTEND; 472ac27a0ecSDave Kleikamp break; 473617ba13bSMingming Cao case EXT4_IOC32_GETVERSION_OLD: 474617ba13bSMingming Cao cmd = EXT4_IOC_GETVERSION_OLD; 475ac27a0ecSDave Kleikamp break; 476617ba13bSMingming Cao case EXT4_IOC32_SETVERSION_OLD: 477617ba13bSMingming Cao cmd = EXT4_IOC_SETVERSION_OLD; 478ac27a0ecSDave Kleikamp break; 479617ba13bSMingming Cao case EXT4_IOC32_GETRSVSZ: 480617ba13bSMingming Cao cmd = EXT4_IOC_GETRSVSZ; 481ac27a0ecSDave Kleikamp break; 482617ba13bSMingming Cao case EXT4_IOC32_SETRSVSZ: 483617ba13bSMingming Cao cmd = EXT4_IOC_SETRSVSZ; 484ac27a0ecSDave Kleikamp break; 4854d92dc0fSBen Hutchings case EXT4_IOC32_GROUP_ADD: { 4864d92dc0fSBen Hutchings struct compat_ext4_new_group_input __user *uinput; 4874d92dc0fSBen Hutchings struct ext4_new_group_input input; 4884d92dc0fSBen Hutchings mm_segment_t old_fs; 4894d92dc0fSBen Hutchings int err; 4904d92dc0fSBen Hutchings 4914d92dc0fSBen Hutchings uinput = compat_ptr(arg); 4924d92dc0fSBen Hutchings err = get_user(input.group, &uinput->group); 4934d92dc0fSBen Hutchings err |= get_user(input.block_bitmap, &uinput->block_bitmap); 4944d92dc0fSBen Hutchings err |= get_user(input.inode_bitmap, &uinput->inode_bitmap); 4954d92dc0fSBen Hutchings err |= get_user(input.inode_table, &uinput->inode_table); 4964d92dc0fSBen Hutchings err |= get_user(input.blocks_count, &uinput->blocks_count); 4974d92dc0fSBen Hutchings err |= get_user(input.reserved_blocks, 4984d92dc0fSBen Hutchings &uinput->reserved_blocks); 4994d92dc0fSBen Hutchings if (err) 5004d92dc0fSBen Hutchings return -EFAULT; 5014d92dc0fSBen Hutchings old_fs = get_fs(); 5024d92dc0fSBen Hutchings set_fs(KERNEL_DS); 5034d92dc0fSBen Hutchings err = ext4_ioctl(file, EXT4_IOC_GROUP_ADD, 5044d92dc0fSBen Hutchings (unsigned long) &input); 5054d92dc0fSBen Hutchings set_fs(old_fs); 5064d92dc0fSBen Hutchings return err; 5074d92dc0fSBen Hutchings } 508b684b2eeSChristian Borntraeger case EXT4_IOC_MOVE_EXT: 509a56e69c2STao Ma case FITRIM: 51019c5246dSYongqiang Yang case EXT4_IOC_RESIZE_FS: 511b684b2eeSChristian Borntraeger break; 512ac27a0ecSDave Kleikamp default: 513ac27a0ecSDave Kleikamp return -ENOIOCTLCMD; 514ac27a0ecSDave Kleikamp } 5155cdd7b2dSAndi Kleen return ext4_ioctl(file, cmd, (unsigned long) compat_ptr(arg)); 516ac27a0ecSDave Kleikamp } 517ac27a0ecSDave Kleikamp #endif 518