blob: eb72cc82b557c765d4c1203d651cec9df1069813 [file] [log] [blame]
Dave Kleikampac27a0e2006-10-11 01:20:50 -07001/*
Mingming Cao617ba132006-10-11 01:20:53 -07002 * linux/fs/ext4/ioctl.c
Dave Kleikampac27a0e2006-10-11 01:20:50 -07003 *
4 * Copyright (C) 1993, 1994, 1995
5 * Remy Card (card@masi.ibp.fr)
6 * Laboratoire MASI - Institut Blaise Pascal
7 * Universite Pierre et Marie Curie (Paris VI)
8 */
9
10#include <linux/fs.h>
Dave Kleikampac27a0e2006-10-11 01:20:50 -070011#include <linux/capability.h>
Dave Kleikampac27a0e2006-10-11 01:20:50 -070012#include <linux/time.h>
13#include <linux/compat.h>
Dave Hansen42a74f22008-02-15 14:37:46 -080014#include <linux/mount.h>
Akira Fujita748de672009-06-17 19:24:03 -040015#include <linux/file.h>
Li Xi9b7365f2016-01-08 16:01:22 -050016#include <linux/quotaops.h>
Andy Shevchenko8da4b8c2016-05-20 17:01:00 -070017#include <linux/uuid.h>
Dave Kleikampac27a0e2006-10-11 01:20:50 -070018#include <asm/uaccess.h>
Christoph Hellwig3dcf5452008-04-29 18:13:32 -040019#include "ext4_jbd2.h"
20#include "ext4.h"
Dave Kleikampac27a0e2006-10-11 01:20:50 -070021
Dr. Tilmann Bubeck393d1d12013-04-08 12:54:05 -040022/**
23 * Swap memory between @a and @b for @len bytes.
24 *
25 * @a: pointer to first memory area
26 * @b: pointer to second memory area
27 * @len: number of bytes to swap
28 *
29 */
30static void memswap(void *a, void *b, size_t len)
31{
32 unsigned char *ap, *bp;
Dr. Tilmann Bubeck393d1d12013-04-08 12:54:05 -040033
34 ap = (unsigned char *)a;
35 bp = (unsigned char *)b;
36 while (len-- > 0) {
Fabian Frederick4b7e2db2015-06-12 23:46:33 -040037 swap(*ap, *bp);
Dr. Tilmann Bubeck393d1d12013-04-08 12:54:05 -040038 ap++;
39 bp++;
40 }
41}
42
43/**
44 * Swap i_data and associated attributes between @inode1 and @inode2.
45 * This function is used for the primary swap between inode1 and inode2
46 * and also to revert this primary swap in case of errors.
47 *
48 * Therefore you have to make sure, that calling this method twice
49 * will revert all changes.
50 *
51 * @inode1: pointer to first inode
52 * @inode2: pointer to second inode
53 */
54static void swap_inode_data(struct inode *inode1, struct inode *inode2)
55{
56 loff_t isize;
57 struct ext4_inode_info *ei1;
58 struct ext4_inode_info *ei2;
59
60 ei1 = EXT4_I(inode1);
61 ei2 = EXT4_I(inode2);
62
63 memswap(&inode1->i_flags, &inode2->i_flags, sizeof(inode1->i_flags));
64 memswap(&inode1->i_version, &inode2->i_version,
65 sizeof(inode1->i_version));
66 memswap(&inode1->i_blocks, &inode2->i_blocks,
67 sizeof(inode1->i_blocks));
68 memswap(&inode1->i_bytes, &inode2->i_bytes, sizeof(inode1->i_bytes));
69 memswap(&inode1->i_atime, &inode2->i_atime, sizeof(inode1->i_atime));
70 memswap(&inode1->i_mtime, &inode2->i_mtime, sizeof(inode1->i_mtime));
71
72 memswap(ei1->i_data, ei2->i_data, sizeof(ei1->i_data));
73 memswap(&ei1->i_flags, &ei2->i_flags, sizeof(ei1->i_flags));
74 memswap(&ei1->i_disksize, &ei2->i_disksize, sizeof(ei1->i_disksize));
Theodore Ts'ocde2d7a2013-08-12 09:29:30 -040075 ext4_es_remove_extent(inode1, 0, EXT_MAX_BLOCKS);
76 ext4_es_remove_extent(inode2, 0, EXT_MAX_BLOCKS);
Dr. Tilmann Bubeck393d1d12013-04-08 12:54:05 -040077
78 isize = i_size_read(inode1);
79 i_size_write(inode1, i_size_read(inode2));
80 i_size_write(inode2, isize);
81}
82
83/**
84 * Swap the information from the given @inode and the inode
85 * EXT4_BOOT_LOADER_INO. It will basically swap i_data and all other
86 * important fields of the inodes.
87 *
88 * @sb: the super block of the filesystem
89 * @inode: the inode to swap with EXT4_BOOT_LOADER_INO
90 *
91 */
92static long swap_inode_boot_loader(struct super_block *sb,
93 struct inode *inode)
94{
95 handle_t *handle;
96 int err;
97 struct inode *inode_bl;
Dr. Tilmann Bubeck393d1d12013-04-08 12:54:05 -040098 struct ext4_inode_info *ei_bl;
jon ernstd7092ae2014-01-11 13:26:56 -050099 struct ext4_sb_info *sbi = EXT4_SB(sb);
Dr. Tilmann Bubeck393d1d12013-04-08 12:54:05 -0400100
Theodore Ts'od8558a22014-02-17 20:44:36 -0500101 if (inode->i_nlink != 1 || !S_ISREG(inode->i_mode))
102 return -EINVAL;
Dr. Tilmann Bubeck393d1d12013-04-08 12:54:05 -0400103
Theodore Ts'od8558a22014-02-17 20:44:36 -0500104 if (!inode_owner_or_capable(inode) || !capable(CAP_SYS_ADMIN))
105 return -EPERM;
Dr. Tilmann Bubeck393d1d12013-04-08 12:54:05 -0400106
Dr. Tilmann Bubeck393d1d12013-04-08 12:54:05 -0400107 inode_bl = ext4_iget(sb, EXT4_BOOT_LOADER_INO);
Theodore Ts'od8558a22014-02-17 20:44:36 -0500108 if (IS_ERR(inode_bl))
109 return PTR_ERR(inode_bl);
Dr. Tilmann Bubeck393d1d12013-04-08 12:54:05 -0400110 ei_bl = EXT4_I(inode_bl);
111
112 filemap_flush(inode->i_mapping);
113 filemap_flush(inode_bl->i_mapping);
114
115 /* Protect orig inodes against a truncate and make sure,
116 * that only 1 swap_inode_boot_loader is running. */
J. Bruce Fields375e2892012-04-18 15:16:33 -0400117 lock_two_nondirectories(inode, inode_bl);
Dr. Tilmann Bubeck393d1d12013-04-08 12:54:05 -0400118
119 truncate_inode_pages(&inode->i_data, 0);
120 truncate_inode_pages(&inode_bl->i_data, 0);
121
122 /* Wait for all existing dio workers */
123 ext4_inode_block_unlocked_dio(inode);
124 ext4_inode_block_unlocked_dio(inode_bl);
125 inode_dio_wait(inode);
126 inode_dio_wait(inode_bl);
127
128 handle = ext4_journal_start(inode_bl, EXT4_HT_MOVE_EXTENTS, 2);
129 if (IS_ERR(handle)) {
130 err = -EINVAL;
Zheng Liu30d29b12014-02-12 11:48:31 -0500131 goto journal_err_out;
Dr. Tilmann Bubeck393d1d12013-04-08 12:54:05 -0400132 }
133
134 /* Protect extent tree against block allocations via delalloc */
135 ext4_double_down_write_data_sem(inode, inode_bl);
136
137 if (inode_bl->i_nlink == 0) {
138 /* this inode has never been used as a BOOT_LOADER */
139 set_nlink(inode_bl, 1);
140 i_uid_write(inode_bl, 0);
141 i_gid_write(inode_bl, 0);
142 inode_bl->i_flags = 0;
143 ei_bl->i_flags = 0;
144 inode_bl->i_version = 1;
145 i_size_write(inode_bl, 0);
146 inode_bl->i_mode = S_IFREG;
Darrick J. Wonge2b911c2015-10-17 16:18:43 -0400147 if (ext4_has_feature_extents(sb)) {
Dr. Tilmann Bubeck393d1d12013-04-08 12:54:05 -0400148 ext4_set_inode_flag(inode_bl, EXT4_INODE_EXTENTS);
149 ext4_ext_tree_init(handle, inode_bl);
150 } else
151 memset(ei_bl->i_data, 0, sizeof(ei_bl->i_data));
152 }
153
154 swap_inode_data(inode, inode_bl);
155
156 inode->i_ctime = inode_bl->i_ctime = ext4_current_time(inode);
157
158 spin_lock(&sbi->s_next_gen_lock);
159 inode->i_generation = sbi->s_next_generation++;
160 inode_bl->i_generation = sbi->s_next_generation++;
161 spin_unlock(&sbi->s_next_gen_lock);
162
163 ext4_discard_preallocations(inode);
164
165 err = ext4_mark_inode_dirty(handle, inode);
166 if (err < 0) {
167 ext4_warning(inode->i_sb,
168 "couldn't mark inode #%lu dirty (err %d)",
169 inode->i_ino, err);
170 /* Revert all changes: */
171 swap_inode_data(inode, inode_bl);
172 } else {
173 err = ext4_mark_inode_dirty(handle, inode_bl);
174 if (err < 0) {
175 ext4_warning(inode_bl->i_sb,
176 "couldn't mark inode #%lu dirty (err %d)",
177 inode_bl->i_ino, err);
178 /* Revert all changes: */
179 swap_inode_data(inode, inode_bl);
180 ext4_mark_inode_dirty(handle, inode);
181 }
182 }
Dr. Tilmann Bubeck393d1d12013-04-08 12:54:05 -0400183 ext4_journal_stop(handle);
Dr. Tilmann Bubeck393d1d12013-04-08 12:54:05 -0400184 ext4_double_up_write_data_sem(inode, inode_bl);
185
Zheng Liu30d29b12014-02-12 11:48:31 -0500186journal_err_out:
Dr. Tilmann Bubeck393d1d12013-04-08 12:54:05 -0400187 ext4_inode_resume_unlocked_dio(inode);
188 ext4_inode_resume_unlocked_dio(inode_bl);
J. Bruce Fields375e2892012-04-18 15:16:33 -0400189 unlock_two_nondirectories(inode, inode_bl);
Dr. Tilmann Bubeck393d1d12013-04-08 12:54:05 -0400190 iput(inode_bl);
Dr. Tilmann Bubeck393d1d12013-04-08 12:54:05 -0400191 return err;
192}
193
Chandan Rajendra3ce5fa32018-12-12 15:20:12 +0530194#ifdef CONFIG_FS_ENCRYPTION
Michael Halcrow9bd82122015-04-11 07:48:01 -0400195static int uuid_is_zero(__u8 u[16])
196{
197 int i;
198
199 for (i = 0; i < 16; i++)
200 if (u[i])
201 return 0;
202 return 1;
203}
Hyojun Kim63da4202017-10-06 17:10:08 -0700204#endif
Michael Halcrow9bd82122015-04-11 07:48:01 -0400205
Li Xi9b7365f2016-01-08 16:01:22 -0500206static int ext4_ioctl_setflags(struct inode *inode,
207 unsigned int flags)
208{
209 struct ext4_inode_info *ei = EXT4_I(inode);
210 handle_t *handle = NULL;
Anton Protopopovfdde3682016-02-11 23:57:21 -0500211 int err = -EPERM, migrate = 0;
Li Xi9b7365f2016-01-08 16:01:22 -0500212 struct ext4_iloc iloc;
213 unsigned int oldflags, mask, i;
214 unsigned int jflag;
215
216 /* Is it quota file? Do not allow user to mess with it */
217 if (IS_NOQUOTA(inode))
218 goto flags_out;
219
220 oldflags = ei->i_flags;
221
222 /* The JOURNAL_DATA flag is modifiable only by root */
223 jflag = flags & EXT4_JOURNAL_DATA_FL;
224
225 /*
226 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
227 * the relevant capability.
228 *
229 * This test looks nicer. Thanks to Pauline Middelink
230 */
231 if ((flags ^ oldflags) & (EXT4_APPEND_FL | EXT4_IMMUTABLE_FL)) {
232 if (!capable(CAP_LINUX_IMMUTABLE))
233 goto flags_out;
234 }
235
236 /*
237 * The JOURNAL_DATA flag can only be changed by
238 * the relevant capability.
239 */
240 if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) {
241 if (!capable(CAP_SYS_RESOURCE))
242 goto flags_out;
243 }
244 if ((flags ^ oldflags) & EXT4_EXTENTS_FL)
245 migrate = 1;
246
247 if (flags & EXT4_EOFBLOCKS_FL) {
248 /* we don't support adding EOFBLOCKS flag */
249 if (!(oldflags & EXT4_EOFBLOCKS_FL)) {
250 err = -EOPNOTSUPP;
251 goto flags_out;
252 }
253 } else if (oldflags & EXT4_EOFBLOCKS_FL)
254 ext4_truncate(inode);
255
256 handle = ext4_journal_start(inode, EXT4_HT_INODE, 1);
257 if (IS_ERR(handle)) {
258 err = PTR_ERR(handle);
259 goto flags_out;
260 }
261 if (IS_SYNC(inode))
262 ext4_handle_sync(handle);
263 err = ext4_reserve_inode_write(handle, inode, &iloc);
264 if (err)
265 goto flags_err;
266
267 for (i = 0, mask = 1; i < 32; i++, mask <<= 1) {
268 if (!(mask & EXT4_FL_USER_MODIFIABLE))
269 continue;
270 if (mask & flags)
271 ext4_set_inode_flag(inode, i);
272 else
273 ext4_clear_inode_flag(inode, i);
274 }
275
276 ext4_set_inode_flags(inode);
277 inode->i_ctime = ext4_current_time(inode);
278
279 err = ext4_mark_iloc_dirty(handle, inode, &iloc);
280flags_err:
281 ext4_journal_stop(handle);
282 if (err)
283 goto flags_out;
284
285 if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL))
286 err = ext4_change_inode_journal_flag(inode, jflag);
287 if (err)
288 goto flags_out;
289 if (migrate) {
290 if (flags & EXT4_EXTENTS_FL)
291 err = ext4_ext_migrate(inode);
292 else
293 err = ext4_ind_migrate(inode);
294 }
295
296flags_out:
297 return err;
298}
299
300#ifdef CONFIG_QUOTA
301static int ext4_ioctl_setproject(struct file *filp, __u32 projid)
302{
303 struct inode *inode = file_inode(filp);
304 struct super_block *sb = inode->i_sb;
305 struct ext4_inode_info *ei = EXT4_I(inode);
306 int err, rc;
307 handle_t *handle;
308 kprojid_t kprojid;
309 struct ext4_iloc iloc;
310 struct ext4_inode *raw_inode;
Wang Shilong079788d2016-07-05 21:33:52 -0400311 struct dquot *transfer_to[MAXQUOTAS] = { };
Li Xi9b7365f2016-01-08 16:01:22 -0500312
Kaho Ng0b7b7772016-09-05 23:11:58 -0400313 if (!ext4_has_feature_project(sb)) {
Li Xi9b7365f2016-01-08 16:01:22 -0500314 if (projid != EXT4_DEF_PROJID)
315 return -EOPNOTSUPP;
316 else
317 return 0;
318 }
319
320 if (EXT4_INODE_SIZE(sb) <= EXT4_GOOD_OLD_INODE_SIZE)
321 return -EOPNOTSUPP;
322
323 kprojid = make_kprojid(&init_user_ns, (projid_t)projid);
324
325 if (projid_eq(kprojid, EXT4_I(inode)->i_projid))
326 return 0;
327
328 err = mnt_want_write_file(filp);
329 if (err)
330 return err;
331
332 err = -EPERM;
Al Viro59551022016-01-22 15:40:57 -0500333 inode_lock(inode);
Li Xi9b7365f2016-01-08 16:01:22 -0500334 /* Is it quota file? Do not allow user to mess with it */
335 if (IS_NOQUOTA(inode))
336 goto out_unlock;
337
338 err = ext4_get_inode_loc(inode, &iloc);
339 if (err)
340 goto out_unlock;
341
342 raw_inode = ext4_raw_inode(&iloc);
343 if (!EXT4_FITS_IN_INODE(raw_inode, ei, i_projid)) {
344 err = -EOVERFLOW;
345 brelse(iloc.bh);
346 goto out_unlock;
347 }
348 brelse(iloc.bh);
349
Wang Shilong8e308692018-10-03 12:19:21 -0400350 err = dquot_initialize(inode);
351 if (err)
352 return err;
Li Xi9b7365f2016-01-08 16:01:22 -0500353
354 handle = ext4_journal_start(inode, EXT4_HT_QUOTA,
355 EXT4_QUOTA_INIT_BLOCKS(sb) +
356 EXT4_QUOTA_DEL_BLOCKS(sb) + 3);
357 if (IS_ERR(handle)) {
358 err = PTR_ERR(handle);
359 goto out_unlock;
360 }
361
362 err = ext4_reserve_inode_write(handle, inode, &iloc);
363 if (err)
364 goto out_stop;
365
Wang Shilong079788d2016-07-05 21:33:52 -0400366 transfer_to[PRJQUOTA] = dqget(sb, make_kqid_projid(kprojid));
367 if (!IS_ERR(transfer_to[PRJQUOTA])) {
368 err = __dquot_transfer(inode, transfer_to);
369 dqput(transfer_to[PRJQUOTA]);
370 if (err)
371 goto out_dirty;
Li Xi9b7365f2016-01-08 16:01:22 -0500372 }
Wang Shilong079788d2016-07-05 21:33:52 -0400373
Li Xi9b7365f2016-01-08 16:01:22 -0500374 EXT4_I(inode)->i_projid = kprojid;
375 inode->i_ctime = ext4_current_time(inode);
376out_dirty:
377 rc = ext4_mark_iloc_dirty(handle, inode, &iloc);
378 if (!err)
379 err = rc;
380out_stop:
381 ext4_journal_stop(handle);
382out_unlock:
Al Viro59551022016-01-22 15:40:57 -0500383 inode_unlock(inode);
Li Xi9b7365f2016-01-08 16:01:22 -0500384 mnt_drop_write_file(filp);
385 return err;
386}
387#else
388static int ext4_ioctl_setproject(struct file *filp, __u32 projid)
389{
390 if (projid != EXT4_DEF_PROJID)
391 return -EOPNOTSUPP;
392 return 0;
393}
394#endif
395
396/* Transfer internal flags to xflags */
397static inline __u32 ext4_iflags_to_xflags(unsigned long iflags)
398{
399 __u32 xflags = 0;
400
401 if (iflags & EXT4_SYNC_FL)
402 xflags |= FS_XFLAG_SYNC;
403 if (iflags & EXT4_IMMUTABLE_FL)
404 xflags |= FS_XFLAG_IMMUTABLE;
405 if (iflags & EXT4_APPEND_FL)
406 xflags |= FS_XFLAG_APPEND;
407 if (iflags & EXT4_NODUMP_FL)
408 xflags |= FS_XFLAG_NODUMP;
409 if (iflags & EXT4_NOATIME_FL)
410 xflags |= FS_XFLAG_NOATIME;
411 if (iflags & EXT4_PROJINHERIT_FL)
412 xflags |= FS_XFLAG_PROJINHERIT;
413 return xflags;
414}
415
416/* Transfer xflags flags to internal */
417static inline unsigned long ext4_xflags_to_iflags(__u32 xflags)
418{
419 unsigned long iflags = 0;
420
421 if (xflags & FS_XFLAG_SYNC)
422 iflags |= EXT4_SYNC_FL;
423 if (xflags & FS_XFLAG_IMMUTABLE)
424 iflags |= EXT4_IMMUTABLE_FL;
425 if (xflags & FS_XFLAG_APPEND)
426 iflags |= EXT4_APPEND_FL;
427 if (xflags & FS_XFLAG_NODUMP)
428 iflags |= EXT4_NODUMP_FL;
429 if (xflags & FS_XFLAG_NOATIME)
430 iflags |= EXT4_NOATIME_FL;
431 if (xflags & FS_XFLAG_PROJINHERIT)
432 iflags |= EXT4_PROJINHERIT_FL;
433
434 return iflags;
435}
436
Andi Kleen5cdd7b22008-04-29 22:03:54 -0400437long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700438{
Al Viro496ad9a2013-01-23 17:07:38 -0500439 struct inode *inode = file_inode(filp);
Theodore Ts'obab08ab2011-09-09 18:36:51 -0400440 struct super_block *sb = inode->i_sb;
Mingming Cao617ba132006-10-11 01:20:53 -0700441 struct ext4_inode_info *ei = EXT4_I(inode);
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700442 unsigned int flags;
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700443
Theodore Ts'oaf5bc922008-09-08 22:25:24 -0400444 ext4_debug("cmd = %u, arg = %lu\n", cmd, arg);
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700445
446 switch (cmd) {
Mingming Cao617ba132006-10-11 01:20:53 -0700447 case EXT4_IOC_GETFLAGS:
Jan Karaff9ddf72007-07-18 09:24:20 -0400448 ext4_get_inode_flags(ei);
Mingming Cao617ba132006-10-11 01:20:53 -0700449 flags = ei->i_flags & EXT4_FL_USER_VISIBLE;
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700450 return put_user(flags, (int __user *) arg);
Mingming Cao617ba132006-10-11 01:20:53 -0700451 case EXT4_IOC_SETFLAGS: {
Li Xi9b7365f2016-01-08 16:01:22 -0500452 int err;
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700453
Serge E. Hallyn2e149672011-03-23 16:43:26 -0700454 if (!inode_owner_or_capable(inode))
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700455 return -EACCES;
456
457 if (get_user(flags, (int __user *) arg))
458 return -EFAULT;
459
Al Viroa561be72011-11-23 11:57:51 -0500460 err = mnt_want_write_file(filp);
Dave Hansen42a74f22008-02-15 14:37:46 -0800461 if (err)
462 return err;
463
Duane Griffin2dc6b0d2009-02-15 18:09:20 -0500464 flags = ext4_mask_flags(inode->i_mode, flags);
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700465
Al Viro59551022016-01-22 15:40:57 -0500466 inode_lock(inode);
Li Xi9b7365f2016-01-08 16:01:22 -0500467 err = ext4_ioctl_setflags(inode, flags);
Al Viro59551022016-01-22 15:40:57 -0500468 inode_unlock(inode);
Al Viro2a79f172011-12-09 08:06:57 -0500469 mnt_drop_write_file(filp);
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700470 return err;
471 }
Mingming Cao617ba132006-10-11 01:20:53 -0700472 case EXT4_IOC_GETVERSION:
473 case EXT4_IOC_GETVERSION_OLD:
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700474 return put_user(inode->i_generation, (int __user *) arg);
Mingming Cao617ba132006-10-11 01:20:53 -0700475 case EXT4_IOC_SETVERSION:
476 case EXT4_IOC_SETVERSION_OLD: {
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700477 handle_t *handle;
Mingming Cao617ba132006-10-11 01:20:53 -0700478 struct ext4_iloc iloc;
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700479 __u32 generation;
480 int err;
481
Serge E. Hallyn2e149672011-03-23 16:43:26 -0700482 if (!inode_owner_or_capable(inode))
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700483 return -EPERM;
Dave Hansen42a74f22008-02-15 14:37:46 -0800484
Dmitry Monakhov9aa5d322014-10-13 03:36:16 -0400485 if (ext4_has_metadata_csum(inode->i_sb)) {
Darrick J. Wong814525f2012-04-29 18:31:10 -0400486 ext4_warning(sb, "Setting inode version is not "
487 "supported with metadata_csum enabled.");
488 return -ENOTTY;
489 }
490
Al Viroa561be72011-11-23 11:57:51 -0500491 err = mnt_want_write_file(filp);
Dave Hansen42a74f22008-02-15 14:37:46 -0800492 if (err)
493 return err;
494 if (get_user(generation, (int __user *) arg)) {
495 err = -EFAULT;
496 goto setversion_out;
497 }
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700498
Al Viro59551022016-01-22 15:40:57 -0500499 inode_lock(inode);
Theodore Ts'o9924a922013-02-08 21:59:22 -0500500 handle = ext4_journal_start(inode, EXT4_HT_INODE, 1);
Dave Hansen42a74f22008-02-15 14:37:46 -0800501 if (IS_ERR(handle)) {
502 err = PTR_ERR(handle);
Djalal Harouni6c2155b2012-01-03 02:31:52 +0100503 goto unlock_out;
Dave Hansen42a74f22008-02-15 14:37:46 -0800504 }
Mingming Cao617ba132006-10-11 01:20:53 -0700505 err = ext4_reserve_inode_write(handle, inode, &iloc);
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700506 if (err == 0) {
Kalpak Shahef7f3832007-07-18 09:15:20 -0400507 inode->i_ctime = ext4_current_time(inode);
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700508 inode->i_generation = generation;
Mingming Cao617ba132006-10-11 01:20:53 -0700509 err = ext4_mark_iloc_dirty(handle, inode, &iloc);
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700510 }
Mingming Cao617ba132006-10-11 01:20:53 -0700511 ext4_journal_stop(handle);
Djalal Harouni6c2155b2012-01-03 02:31:52 +0100512
513unlock_out:
Al Viro59551022016-01-22 15:40:57 -0500514 inode_unlock(inode);
Dave Hansen42a74f22008-02-15 14:37:46 -0800515setversion_out:
Al Viro2a79f172011-12-09 08:06:57 -0500516 mnt_drop_write_file(filp);
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700517 return err;
518 }
Mingming Cao617ba132006-10-11 01:20:53 -0700519 case EXT4_IOC_GROUP_EXTEND: {
520 ext4_fsblk_t n_blocks_count;
Peng Taoac046f12009-07-13 09:30:17 -0400521 int err, err2=0;
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700522
Yongqiang Yang8f82f842011-07-26 21:35:44 -0400523 err = ext4_resize_begin(sb);
524 if (err)
525 return err;
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700526
Djalal Harouni014a1772012-01-04 17:09:52 -0500527 if (get_user(n_blocks_count, (__u32 __user *)arg)) {
528 err = -EFAULT;
529 goto group_extend_out;
530 }
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700531
Darrick J. Wonge2b911c2015-10-17 16:18:43 -0400532 if (ext4_has_feature_bigalloc(sb)) {
Theodore Ts'obab08ab2011-09-09 18:36:51 -0400533 ext4_msg(sb, KERN_ERR,
534 "Online resizing not supported with bigalloc");
Djalal Harouni014a1772012-01-04 17:09:52 -0500535 err = -EOPNOTSUPP;
536 goto group_extend_out;
Theodore Ts'obab08ab2011-09-09 18:36:51 -0400537 }
538
Al Viroa561be72011-11-23 11:57:51 -0500539 err = mnt_want_write_file(filp);
Dave Hansen42a74f22008-02-15 14:37:46 -0800540 if (err)
Djalal Harouni014a1772012-01-04 17:09:52 -0500541 goto group_extend_out;
Dave Hansen42a74f22008-02-15 14:37:46 -0800542
Mingming Cao617ba132006-10-11 01:20:53 -0700543 err = ext4_group_extend(sb, EXT4_SB(sb)->s_es, n_blocks_count);
Peng Taoac046f12009-07-13 09:30:17 -0400544 if (EXT4_SB(sb)->s_journal) {
545 jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal);
546 err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal);
547 jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
548 }
Hidehiro Kawai7ffe1ea2008-10-10 20:29:21 -0400549 if (err == 0)
550 err = err2;
Al Viro2a79f172011-12-09 08:06:57 -0500551 mnt_drop_write_file(filp);
Djalal Harouni014a1772012-01-04 17:09:52 -0500552group_extend_out:
Yongqiang Yang8f82f842011-07-26 21:35:44 -0400553 ext4_resize_end(sb);
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700554 return err;
555 }
Akira Fujita748de672009-06-17 19:24:03 -0400556
557 case EXT4_IOC_MOVE_EXT: {
558 struct move_extent me;
Al Viro2903ff02012-08-28 12:52:22 -0400559 struct fd donor;
560 int err;
Akira Fujita748de672009-06-17 19:24:03 -0400561
Akira Fujita4a585792009-12-06 23:38:31 -0500562 if (!(filp->f_mode & FMODE_READ) ||
563 !(filp->f_mode & FMODE_WRITE))
564 return -EBADF;
565
Akira Fujita748de672009-06-17 19:24:03 -0400566 if (copy_from_user(&me,
567 (struct move_extent __user *)arg, sizeof(me)))
568 return -EFAULT;
Akira Fujita4a585792009-12-06 23:38:31 -0500569 me.moved_len = 0;
Akira Fujita748de672009-06-17 19:24:03 -0400570
Al Viro2903ff02012-08-28 12:52:22 -0400571 donor = fdget(me.donor_fd);
572 if (!donor.file)
Akira Fujita748de672009-06-17 19:24:03 -0400573 return -EBADF;
574
Al Viro2903ff02012-08-28 12:52:22 -0400575 if (!(donor.file->f_mode & FMODE_WRITE)) {
Akira Fujita4a585792009-12-06 23:38:31 -0500576 err = -EBADF;
577 goto mext_out;
Akira Fujita748de672009-06-17 19:24:03 -0400578 }
579
Darrick J. Wonge2b911c2015-10-17 16:18:43 -0400580 if (ext4_has_feature_bigalloc(sb)) {
Theodore Ts'obab08ab2011-09-09 18:36:51 -0400581 ext4_msg(sb, KERN_ERR,
582 "Online defrag not supported with bigalloc");
Al Viro399c9b82012-08-26 21:00:03 -0400583 err = -EOPNOTSUPP;
584 goto mext_out;
Ross Zwisler73f34a52016-02-26 15:19:49 -0800585 } else if (IS_DAX(inode)) {
586 ext4_msg(sb, KERN_ERR,
587 "Online defrag not supported with DAX");
588 err = -EOPNOTSUPP;
589 goto mext_out;
Theodore Ts'obab08ab2011-09-09 18:36:51 -0400590 }
591
Al Viroa561be72011-11-23 11:57:51 -0500592 err = mnt_want_write_file(filp);
Akira Fujita4a585792009-12-06 23:38:31 -0500593 if (err)
594 goto mext_out;
595
Al Viro2903ff02012-08-28 12:52:22 -0400596 err = ext4_move_extents(filp, donor.file, me.orig_start,
Akira Fujita748de672009-06-17 19:24:03 -0400597 me.donor_start, me.len, &me.moved_len);
Al Viro2a79f172011-12-09 08:06:57 -0500598 mnt_drop_write_file(filp);
Akira Fujita748de672009-06-17 19:24:03 -0400599
Theodore Ts'o60e66792010-05-17 07:00:00 -0400600 if (copy_to_user((struct move_extent __user *)arg,
Akira Fujitac437b272010-03-04 00:39:24 -0500601 &me, sizeof(me)))
Akira Fujita4a585792009-12-06 23:38:31 -0500602 err = -EFAULT;
603mext_out:
Al Viro2903ff02012-08-28 12:52:22 -0400604 fdput(donor);
Akira Fujita748de672009-06-17 19:24:03 -0400605 return err;
606 }
607
Mingming Cao617ba132006-10-11 01:20:53 -0700608 case EXT4_IOC_GROUP_ADD: {
609 struct ext4_new_group_data input;
Peng Taoac046f12009-07-13 09:30:17 -0400610 int err, err2=0;
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700611
Yongqiang Yang8f82f842011-07-26 21:35:44 -0400612 err = ext4_resize_begin(sb);
613 if (err)
614 return err;
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700615
Mingming Cao617ba132006-10-11 01:20:53 -0700616 if (copy_from_user(&input, (struct ext4_new_group_input __user *)arg,
Djalal Harouni014a1772012-01-04 17:09:52 -0500617 sizeof(input))) {
618 err = -EFAULT;
619 goto group_add_out;
620 }
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700621
Darrick J. Wonge2b911c2015-10-17 16:18:43 -0400622 if (ext4_has_feature_bigalloc(sb)) {
Theodore Ts'obab08ab2011-09-09 18:36:51 -0400623 ext4_msg(sb, KERN_ERR,
624 "Online resizing not supported with bigalloc");
Djalal Harouni014a1772012-01-04 17:09:52 -0500625 err = -EOPNOTSUPP;
626 goto group_add_out;
Theodore Ts'obab08ab2011-09-09 18:36:51 -0400627 }
628
Al Viroa561be72011-11-23 11:57:51 -0500629 err = mnt_want_write_file(filp);
Dave Hansen42a74f22008-02-15 14:37:46 -0800630 if (err)
Djalal Harouni014a1772012-01-04 17:09:52 -0500631 goto group_add_out;
Dave Hansen42a74f22008-02-15 14:37:46 -0800632
Mingming Cao617ba132006-10-11 01:20:53 -0700633 err = ext4_group_add(sb, &input);
Peng Taoac046f12009-07-13 09:30:17 -0400634 if (EXT4_SB(sb)->s_journal) {
635 jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal);
636 err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal);
637 jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
638 }
Hidehiro Kawai7ffe1ea2008-10-10 20:29:21 -0400639 if (err == 0)
640 err = err2;
Al Viro2a79f172011-12-09 08:06:57 -0500641 mnt_drop_write_file(filp);
Theodore Ts'o7f511862013-01-13 08:41:45 -0500642 if (!err && ext4_has_group_desc_csum(sb) &&
643 test_opt(sb, INIT_INODE_TABLE))
644 err = ext4_register_li_request(sb, input.group);
Djalal Harouni014a1772012-01-04 17:09:52 -0500645group_add_out:
Yongqiang Yang8f82f842011-07-26 21:35:44 -0400646 ext4_resize_end(sb);
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700647 return err;
648 }
649
Aneesh Kumar K.Vc14c6fd2008-01-28 23:58:26 -0500650 case EXT4_IOC_MIGRATE:
Aneesh Kumar K.V2a43a872008-09-13 12:52:26 -0400651 {
652 int err;
Serge E. Hallyn2e149672011-03-23 16:43:26 -0700653 if (!inode_owner_or_capable(inode))
Aneesh Kumar K.V2a43a872008-09-13 12:52:26 -0400654 return -EACCES;
655
Al Viroa561be72011-11-23 11:57:51 -0500656 err = mnt_want_write_file(filp);
Aneesh Kumar K.V2a43a872008-09-13 12:52:26 -0400657 if (err)
658 return err;
659 /*
660 * inode_mutex prevent write and truncate on the file.
661 * Read still goes through. We take i_data_sem in
662 * ext4_ext_swap_inode_data before we switch the
663 * inode format to prevent read.
664 */
Al Viro59551022016-01-22 15:40:57 -0500665 inode_lock((inode));
Aneesh Kumar K.V2a43a872008-09-13 12:52:26 -0400666 err = ext4_ext_migrate(inode);
Al Viro59551022016-01-22 15:40:57 -0500667 inode_unlock((inode));
Al Viro2a79f172011-12-09 08:06:57 -0500668 mnt_drop_write_file(filp);
Aneesh Kumar K.V2a43a872008-09-13 12:52:26 -0400669 return err;
670 }
Aneesh Kumar K.Vc14c6fd2008-01-28 23:58:26 -0500671
Theodore Ts'occd25062009-02-26 01:04:07 -0500672 case EXT4_IOC_ALLOC_DA_BLKS:
673 {
674 int err;
Serge E. Hallyn2e149672011-03-23 16:43:26 -0700675 if (!inode_owner_or_capable(inode))
Theodore Ts'occd25062009-02-26 01:04:07 -0500676 return -EACCES;
677
Al Viroa561be72011-11-23 11:57:51 -0500678 err = mnt_want_write_file(filp);
Theodore Ts'occd25062009-02-26 01:04:07 -0500679 if (err)
680 return err;
681 err = ext4_alloc_da_blocks(inode);
Al Viro2a79f172011-12-09 08:06:57 -0500682 mnt_drop_write_file(filp);
Theodore Ts'occd25062009-02-26 01:04:07 -0500683 return err;
684 }
685
Dr. Tilmann Bubeck393d1d12013-04-08 12:54:05 -0400686 case EXT4_IOC_SWAP_BOOT:
Dmitry Monakhov3e67cfad22014-10-03 12:47:23 -0400687 {
688 int err;
Dr. Tilmann Bubeck393d1d12013-04-08 12:54:05 -0400689 if (!(filp->f_mode & FMODE_WRITE))
690 return -EBADF;
Dmitry Monakhov3e67cfad22014-10-03 12:47:23 -0400691 err = mnt_want_write_file(filp);
692 if (err)
693 return err;
694 err = swap_inode_boot_loader(sb, inode);
695 mnt_drop_write_file(filp);
696 return err;
697 }
Dr. Tilmann Bubeck393d1d12013-04-08 12:54:05 -0400698
Yongqiang Yang19c52462012-01-04 17:09:44 -0500699 case EXT4_IOC_RESIZE_FS: {
700 ext4_fsblk_t n_blocks_count;
Yongqiang Yang19c52462012-01-04 17:09:44 -0500701 int err = 0, err2 = 0;
Theodore Ts'o7f511862013-01-13 08:41:45 -0500702 ext4_group_t o_group = EXT4_SB(sb)->s_groups_count;
Yongqiang Yang19c52462012-01-04 17:09:44 -0500703
Darrick J. Wonge2b911c2015-10-17 16:18:43 -0400704 if (ext4_has_feature_bigalloc(sb)) {
Yongqiang Yang19c52462012-01-04 17:09:44 -0500705 ext4_msg(sb, KERN_ERR,
706 "Online resizing not (yet) supported with bigalloc");
707 return -EOPNOTSUPP;
708 }
709
Yongqiang Yang19c52462012-01-04 17:09:44 -0500710 if (copy_from_user(&n_blocks_count, (__u64 __user *)arg,
711 sizeof(__u64))) {
712 return -EFAULT;
713 }
714
Yongqiang Yang19c52462012-01-04 17:09:44 -0500715 err = ext4_resize_begin(sb);
716 if (err)
717 return err;
718
Al Viro8cae6f72012-07-19 11:19:07 +0400719 err = mnt_want_write_file(filp);
Yongqiang Yang19c52462012-01-04 17:09:44 -0500720 if (err)
721 goto resizefs_out;
722
723 err = ext4_resize_fs(sb, n_blocks_count);
724 if (EXT4_SB(sb)->s_journal) {
725 jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal);
726 err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal);
727 jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
728 }
729 if (err == 0)
730 err = err2;
Al Viro8cae6f72012-07-19 11:19:07 +0400731 mnt_drop_write_file(filp);
Kirill Tkhai083b19c2019-04-25 13:06:18 -0400732 if (!err && (o_group < EXT4_SB(sb)->s_groups_count) &&
Theodore Ts'o7f511862013-01-13 08:41:45 -0500733 ext4_has_group_desc_csum(sb) &&
734 test_opt(sb, INIT_INODE_TABLE))
735 err = ext4_register_li_request(sb, o_group);
736
Yongqiang Yang19c52462012-01-04 17:09:44 -0500737resizefs_out:
738 ext4_resize_end(sb);
739 return err;
740 }
741
JP Abgrallcc14b9e2014-07-23 16:55:07 -0700742 case FIDTRIM:
Lukas Czernere681c042010-11-19 21:47:07 -0500743 case FITRIM:
744 {
Lukas Czerner41431792011-02-23 12:42:32 -0500745 struct request_queue *q = bdev_get_queue(sb->s_bdev);
Lukas Czernere681c042010-11-19 21:47:07 -0500746 struct fstrim_range range;
747 int ret = 0;
JP Abgrallcc14b9e2014-07-23 16:55:07 -0700748 int flags = cmd == FIDTRIM ? BLKDEV_DISCARD_SECURE : 0;
Lukas Czernere681c042010-11-19 21:47:07 -0500749
750 if (!capable(CAP_SYS_ADMIN))
751 return -EPERM;
752
Lukas Czerner41431792011-02-23 12:42:32 -0500753 if (!blk_queue_discard(q))
754 return -EOPNOTSUPP;
755
JP Abgrallcc14b9e2014-07-23 16:55:07 -0700756 if ((flags & BLKDEV_DISCARD_SECURE) && !blk_queue_secure_erase(q))
757 return -EOPNOTSUPP;
758
Darrick J. Wong7e800062019-03-23 12:10:29 -0400759 /*
760 * We haven't replayed the journal, so we cannot use our
761 * block-bitmap-guided storage zapping commands.
762 */
763 if (test_opt(sb, NOLOAD) && ext4_has_feature_journal(sb))
764 return -EROFS;
765
H Hartley Sweetene6705f72011-10-18 10:59:51 -0400766 if (copy_from_user(&range, (struct fstrim_range __user *)arg,
Lukas Czernere681c042010-11-19 21:47:07 -0500767 sizeof(range)))
768 return -EFAULT;
769
Lukas Czerner5c2ed622011-02-23 17:49:51 -0500770 range.minlen = max((unsigned int)range.minlen,
771 q->limits.discard_granularity);
JP Abgrallcc14b9e2014-07-23 16:55:07 -0700772 ret = ext4_trim_fs(sb, &range, flags);
Lukas Czernere681c042010-11-19 21:47:07 -0500773 if (ret < 0)
774 return ret;
775
H Hartley Sweetene6705f72011-10-18 10:59:51 -0400776 if (copy_to_user((struct fstrim_range __user *)arg, &range,
Lukas Czernere681c042010-11-19 21:47:07 -0500777 sizeof(range)))
778 return -EFAULT;
779
780 return 0;
781 }
Theodore Ts'o7869a4a2013-08-16 22:05:14 -0400782 case EXT4_IOC_PRECACHE_EXTENTS:
783 return ext4_ext_precache(inode);
Lukas Czernere681c042010-11-19 21:47:07 -0500784
Hyojun Kim63da4202017-10-06 17:10:08 -0700785 case EXT4_IOC_SET_ENCRYPTION_POLICY:
Neeraj Sonic692cb92018-04-18 17:20:22 +0530786// if (!ext4_has_feature_encrypt(sb))
787// return -EOPNOTSUPP;
Hyojun Kim63da4202017-10-06 17:10:08 -0700788 return fscrypt_ioctl_set_policy(filp, (const void __user *)arg);
Richard Weinberger9a200d02016-09-30 01:49:55 -0400789
Michael Halcrow9bd82122015-04-11 07:48:01 -0400790 case EXT4_IOC_GET_ENCRYPTION_PWSALT: {
Chandan Rajendra3ce5fa32018-12-12 15:20:12 +0530791#ifdef CONFIG_FS_ENCRYPTION
Michael Halcrow9bd82122015-04-11 07:48:01 -0400792 int err, err2;
793 struct ext4_sb_info *sbi = EXT4_SB(sb);
794 handle_t *handle;
795
Hyojun Kim63da4202017-10-06 17:10:08 -0700796 if (!ext4_has_feature_encrypt(sb))
Michael Halcrow9bd82122015-04-11 07:48:01 -0400797 return -EOPNOTSUPP;
798 if (uuid_is_zero(sbi->s_es->s_encrypt_pw_salt)) {
799 err = mnt_want_write_file(filp);
800 if (err)
801 return err;
802 handle = ext4_journal_start_sb(sb, EXT4_HT_MISC, 1);
803 if (IS_ERR(handle)) {
804 err = PTR_ERR(handle);
805 goto pwsalt_err_exit;
806 }
807 err = ext4_journal_get_write_access(handle, sbi->s_sbh);
808 if (err)
809 goto pwsalt_err_journal;
810 generate_random_uuid(sbi->s_es->s_encrypt_pw_salt);
811 err = ext4_handle_dirty_metadata(handle, NULL,
812 sbi->s_sbh);
813 pwsalt_err_journal:
814 err2 = ext4_journal_stop(handle);
815 if (err2 && !err)
816 err = err2;
817 pwsalt_err_exit:
818 mnt_drop_write_file(filp);
819 if (err)
820 return err;
821 }
Fabian Frederickb4ab9e22015-06-08 12:23:21 -0400822 if (copy_to_user((void __user *) arg,
823 sbi->s_es->s_encrypt_pw_salt, 16))
Michael Halcrow9bd82122015-04-11 07:48:01 -0400824 return -EFAULT;
825 return 0;
Michael Halcrow9bd82122015-04-11 07:48:01 -0400826#else
827 return -EOPNOTSUPP;
828#endif
829 }
Hyojun Kim63da4202017-10-06 17:10:08 -0700830 case EXT4_IOC_GET_ENCRYPTION_POLICY:
831 return fscrypt_ioctl_get_policy(filp, (void __user *)arg);
832
Li Xi9b7365f2016-01-08 16:01:22 -0500833 case EXT4_IOC_FSGETXATTR:
834 {
835 struct fsxattr fa;
836
837 memset(&fa, 0, sizeof(struct fsxattr));
Li Xi9b7365f2016-01-08 16:01:22 -0500838 fa.fsx_xflags = ext4_iflags_to_xflags(ei->i_flags & EXT4_FL_USER_VISIBLE);
839
Kaho Ng0b7b7772016-09-05 23:11:58 -0400840 if (ext4_has_feature_project(inode->i_sb)) {
Li Xi9b7365f2016-01-08 16:01:22 -0500841 fa.fsx_projid = (__u32)from_kprojid(&init_user_ns,
842 EXT4_I(inode)->i_projid);
843 }
844
845 if (copy_to_user((struct fsxattr __user *)arg,
846 &fa, sizeof(fa)))
847 return -EFAULT;
848 return 0;
849 }
850 case EXT4_IOC_FSSETXATTR:
851 {
852 struct fsxattr fa;
853 int err;
854
855 if (copy_from_user(&fa, (struct fsxattr __user *)arg,
856 sizeof(fa)))
857 return -EFAULT;
858
859 /* Make sure caller has proper permission */
860 if (!inode_owner_or_capable(inode))
861 return -EACCES;
862
863 err = mnt_want_write_file(filp);
864 if (err)
865 return err;
866
867 flags = ext4_xflags_to_iflags(fa.fsx_xflags);
868 flags = ext4_mask_flags(inode->i_mode, flags);
869
Al Viro59551022016-01-22 15:40:57 -0500870 inode_lock(inode);
Li Xi9b7365f2016-01-08 16:01:22 -0500871 flags = (ei->i_flags & ~EXT4_FL_XFLAG_VISIBLE) |
872 (flags & EXT4_FL_XFLAG_VISIBLE);
873 err = ext4_ioctl_setflags(inode, flags);
Al Viro59551022016-01-22 15:40:57 -0500874 inode_unlock(inode);
Li Xi9b7365f2016-01-08 16:01:22 -0500875 mnt_drop_write_file(filp);
876 if (err)
877 return err;
878
879 err = ext4_ioctl_setproject(filp, fa.fsx_projid);
880 if (err)
881 return err;
882
883 return 0;
884 }
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700885 default:
886 return -ENOTTY;
887 }
888}
889
890#ifdef CONFIG_COMPAT
Mingming Cao617ba132006-10-11 01:20:53 -0700891long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700892{
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700893 /* These are just misnamed, they actually get/put from/to user an int */
894 switch (cmd) {
Mingming Cao617ba132006-10-11 01:20:53 -0700895 case EXT4_IOC32_GETFLAGS:
896 cmd = EXT4_IOC_GETFLAGS;
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700897 break;
Mingming Cao617ba132006-10-11 01:20:53 -0700898 case EXT4_IOC32_SETFLAGS:
899 cmd = EXT4_IOC_SETFLAGS;
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700900 break;
Mingming Cao617ba132006-10-11 01:20:53 -0700901 case EXT4_IOC32_GETVERSION:
902 cmd = EXT4_IOC_GETVERSION;
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700903 break;
Mingming Cao617ba132006-10-11 01:20:53 -0700904 case EXT4_IOC32_SETVERSION:
905 cmd = EXT4_IOC_SETVERSION;
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700906 break;
Mingming Cao617ba132006-10-11 01:20:53 -0700907 case EXT4_IOC32_GROUP_EXTEND:
908 cmd = EXT4_IOC_GROUP_EXTEND;
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700909 break;
Mingming Cao617ba132006-10-11 01:20:53 -0700910 case EXT4_IOC32_GETVERSION_OLD:
911 cmd = EXT4_IOC_GETVERSION_OLD;
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700912 break;
Mingming Cao617ba132006-10-11 01:20:53 -0700913 case EXT4_IOC32_SETVERSION_OLD:
914 cmd = EXT4_IOC_SETVERSION_OLD;
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700915 break;
Mingming Cao617ba132006-10-11 01:20:53 -0700916 case EXT4_IOC32_GETRSVSZ:
917 cmd = EXT4_IOC_GETRSVSZ;
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700918 break;
Mingming Cao617ba132006-10-11 01:20:53 -0700919 case EXT4_IOC32_SETRSVSZ:
920 cmd = EXT4_IOC_SETRSVSZ;
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700921 break;
Ben Hutchings4d92dc02010-05-17 06:00:00 -0400922 case EXT4_IOC32_GROUP_ADD: {
923 struct compat_ext4_new_group_input __user *uinput;
924 struct ext4_new_group_input input;
925 mm_segment_t old_fs;
926 int err;
927
928 uinput = compat_ptr(arg);
929 err = get_user(input.group, &uinput->group);
930 err |= get_user(input.block_bitmap, &uinput->block_bitmap);
931 err |= get_user(input.inode_bitmap, &uinput->inode_bitmap);
932 err |= get_user(input.inode_table, &uinput->inode_table);
933 err |= get_user(input.blocks_count, &uinput->blocks_count);
934 err |= get_user(input.reserved_blocks,
935 &uinput->reserved_blocks);
936 if (err)
937 return -EFAULT;
938 old_fs = get_fs();
939 set_fs(KERNEL_DS);
940 err = ext4_ioctl(file, EXT4_IOC_GROUP_ADD,
941 (unsigned long) &input);
942 set_fs(old_fs);
943 return err;
944 }
Christian Borntraegerb684b2e2010-05-15 00:00:00 -0400945 case EXT4_IOC_MOVE_EXT:
Yongqiang Yang19c52462012-01-04 17:09:44 -0500946 case EXT4_IOC_RESIZE_FS:
Theodore Ts'o7869a4a2013-08-16 22:05:14 -0400947 case EXT4_IOC_PRECACHE_EXTENTS:
Michael Halcrow9bd82122015-04-11 07:48:01 -0400948 case EXT4_IOC_SET_ENCRYPTION_POLICY:
949 case EXT4_IOC_GET_ENCRYPTION_PWSALT:
950 case EXT4_IOC_GET_ENCRYPTION_POLICY:
Christian Borntraegerb684b2e2010-05-15 00:00:00 -0400951 break;
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700952 default:
953 return -ENOIOCTLCMD;
954 }
Andi Kleen5cdd7b22008-04-29 22:03:54 -0400955 return ext4_ioctl(file, cmd, (unsigned long) compat_ptr(arg));
Dave Kleikampac27a0e2006-10-11 01:20:50 -0700956}
957#endif