Blame view

fs/ext4/ioctl.c 22.7 KB
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1
  /*
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
2
   * linux/fs/ext4/ioctl.c
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
3
4
5
6
7
8
9
10
   *
   * Copyright (C) 1993, 1994, 1995
   * Remy Card (card@masi.ibp.fr)
   * Laboratoire MASI - Institut Blaise Pascal
   * Universite Pierre et Marie Curie (Paris VI)
   */
  
  #include <linux/fs.h>
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
11
  #include <linux/capability.h>
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
12
13
  #include <linux/time.h>
  #include <linux/compat.h>
42a74f206   Dave Hansen   [PATCH] r/o bind ...
14
  #include <linux/mount.h>
748de6736   Akira Fujita   ext4: online defr...
15
  #include <linux/file.h>
9b7365fc1   Li Xi   ext4: add FS_IOC_...
16
  #include <linux/quotaops.h>
8da4b8c48   Andy Shevchenko   lib/uuid.c: move ...
17
  #include <linux/uuid.h>
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
18
  #include <asm/uaccess.h>
3dcf54515   Christoph Hellwig   ext4: move header...
19
20
  #include "ext4_jbd2.h"
  #include "ext4.h"
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
21

393d1d1d7   Dr. Tilmann Bubeck   ext4: implementat...
22
23
24
25
26
27
28
29
30
31
32
  /**
   * Swap memory between @a and @b for @len bytes.
   *
   * @a:          pointer to first memory area
   * @b:          pointer to second memory area
   * @len:        number of bytes to swap
   *
   */
  static void memswap(void *a, void *b, size_t len)
  {
  	unsigned char *ap, *bp;
393d1d1d7   Dr. Tilmann Bubeck   ext4: implementat...
33
34
35
36
  
  	ap = (unsigned char *)a;
  	bp = (unsigned char *)b;
  	while (len-- > 0) {
4b7e2db5c   Fabian Frederick   ext4: use swap() ...
37
  		swap(*ap, *bp);
393d1d1d7   Dr. Tilmann Bubeck   ext4: implementat...
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
  		ap++;
  		bp++;
  	}
  }
  
  /**
   * Swap i_data and associated attributes between @inode1 and @inode2.
   * This function is used for the primary swap between inode1 and inode2
   * and also to revert this primary swap in case of errors.
   *
   * Therefore you have to make sure, that calling this method twice
   * will revert all changes.
   *
   * @inode1:     pointer to first inode
   * @inode2:     pointer to second inode
   */
  static void swap_inode_data(struct inode *inode1, struct inode *inode2)
  {
  	loff_t isize;
  	struct ext4_inode_info *ei1;
  	struct ext4_inode_info *ei2;
  
  	ei1 = EXT4_I(inode1);
  	ei2 = EXT4_I(inode2);
  
  	memswap(&inode1->i_flags, &inode2->i_flags, sizeof(inode1->i_flags));
  	memswap(&inode1->i_version, &inode2->i_version,
  		  sizeof(inode1->i_version));
  	memswap(&inode1->i_blocks, &inode2->i_blocks,
  		  sizeof(inode1->i_blocks));
  	memswap(&inode1->i_bytes, &inode2->i_bytes, sizeof(inode1->i_bytes));
  	memswap(&inode1->i_atime, &inode2->i_atime, sizeof(inode1->i_atime));
  	memswap(&inode1->i_mtime, &inode2->i_mtime, sizeof(inode1->i_mtime));
  
  	memswap(ei1->i_data, ei2->i_data, sizeof(ei1->i_data));
  	memswap(&ei1->i_flags, &ei2->i_flags, sizeof(ei1->i_flags));
  	memswap(&ei1->i_disksize, &ei2->i_disksize, sizeof(ei1->i_disksize));
cde2d7a79   Theodore Ts'o   ext4: flush the e...
75
76
  	ext4_es_remove_extent(inode1, 0, EXT_MAX_BLOCKS);
  	ext4_es_remove_extent(inode2, 0, EXT_MAX_BLOCKS);
393d1d1d7   Dr. Tilmann Bubeck   ext4: implementat...
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
  
  	isize = i_size_read(inode1);
  	i_size_write(inode1, i_size_read(inode2));
  	i_size_write(inode2, isize);
  }
  
  /**
   * Swap the information from the given @inode and the inode
   * EXT4_BOOT_LOADER_INO. It will basically swap i_data and all other
   * important fields of the inodes.
   *
   * @sb:         the super block of the filesystem
   * @inode:      the inode to swap with EXT4_BOOT_LOADER_INO
   *
   */
  static long swap_inode_boot_loader(struct super_block *sb,
  				struct inode *inode)
  {
  	handle_t *handle;
  	int err;
  	struct inode *inode_bl;
393d1d1d7   Dr. Tilmann Bubeck   ext4: implementat...
98
  	struct ext4_inode_info *ei_bl;
d7092ae29   jon ernst   ext4: delete "set...
99
  	struct ext4_sb_info *sbi = EXT4_SB(sb);
393d1d1d7   Dr. Tilmann Bubeck   ext4: implementat...
100

d8558a297   Theodore Ts'o   ext4: clean up er...
101
102
  	if (inode->i_nlink != 1 || !S_ISREG(inode->i_mode))
  		return -EINVAL;
393d1d1d7   Dr. Tilmann Bubeck   ext4: implementat...
103

d8558a297   Theodore Ts'o   ext4: clean up er...
104
105
  	if (!inode_owner_or_capable(inode) || !capable(CAP_SYS_ADMIN))
  		return -EPERM;
393d1d1d7   Dr. Tilmann Bubeck   ext4: implementat...
106

393d1d1d7   Dr. Tilmann Bubeck   ext4: implementat...
107
  	inode_bl = ext4_iget(sb, EXT4_BOOT_LOADER_INO);
d8558a297   Theodore Ts'o   ext4: clean up er...
108
109
  	if (IS_ERR(inode_bl))
  		return PTR_ERR(inode_bl);
393d1d1d7   Dr. Tilmann Bubeck   ext4: implementat...
110
111
112
113
114
115
116
  	ei_bl = EXT4_I(inode_bl);
  
  	filemap_flush(inode->i_mapping);
  	filemap_flush(inode_bl->i_mapping);
  
  	/* Protect orig inodes against a truncate and make sure,
  	 * that only 1 swap_inode_boot_loader is running. */
375e289ea   J. Bruce Fields   vfs: pull ext4's ...
117
  	lock_two_nondirectories(inode, inode_bl);
393d1d1d7   Dr. Tilmann Bubeck   ext4: implementat...
118
119
120
121
122
123
124
125
126
127
128
129
130
  
  	truncate_inode_pages(&inode->i_data, 0);
  	truncate_inode_pages(&inode_bl->i_data, 0);
  
  	/* Wait for all existing dio workers */
  	ext4_inode_block_unlocked_dio(inode);
  	ext4_inode_block_unlocked_dio(inode_bl);
  	inode_dio_wait(inode);
  	inode_dio_wait(inode_bl);
  
  	handle = ext4_journal_start(inode_bl, EXT4_HT_MOVE_EXTENTS, 2);
  	if (IS_ERR(handle)) {
  		err = -EINVAL;
30d29b119   Zheng Liu   ext4: fix error p...
131
  		goto journal_err_out;
393d1d1d7   Dr. Tilmann Bubeck   ext4: implementat...
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
  	}
  
  	/* Protect extent tree against block allocations via delalloc */
  	ext4_double_down_write_data_sem(inode, inode_bl);
  
  	if (inode_bl->i_nlink == 0) {
  		/* this inode has never been used as a BOOT_LOADER */
  		set_nlink(inode_bl, 1);
  		i_uid_write(inode_bl, 0);
  		i_gid_write(inode_bl, 0);
  		inode_bl->i_flags = 0;
  		ei_bl->i_flags = 0;
  		inode_bl->i_version = 1;
  		i_size_write(inode_bl, 0);
  		inode_bl->i_mode = S_IFREG;
e2b911c53   Darrick J. Wong   ext4: clean up fe...
147
  		if (ext4_has_feature_extents(sb)) {
393d1d1d7   Dr. Tilmann Bubeck   ext4: implementat...
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
  			ext4_set_inode_flag(inode_bl, EXT4_INODE_EXTENTS);
  			ext4_ext_tree_init(handle, inode_bl);
  		} else
  			memset(ei_bl->i_data, 0, sizeof(ei_bl->i_data));
  	}
  
  	swap_inode_data(inode, inode_bl);
  
  	inode->i_ctime = inode_bl->i_ctime = ext4_current_time(inode);
  
  	spin_lock(&sbi->s_next_gen_lock);
  	inode->i_generation = sbi->s_next_generation++;
  	inode_bl->i_generation = sbi->s_next_generation++;
  	spin_unlock(&sbi->s_next_gen_lock);
  
  	ext4_discard_preallocations(inode);
  
  	err = ext4_mark_inode_dirty(handle, inode);
  	if (err < 0) {
  		ext4_warning(inode->i_sb,
  			"couldn't mark inode #%lu dirty (err %d)",
  			inode->i_ino, err);
  		/* Revert all changes: */
  		swap_inode_data(inode, inode_bl);
  	} else {
  		err = ext4_mark_inode_dirty(handle, inode_bl);
  		if (err < 0) {
  			ext4_warning(inode_bl->i_sb,
  				"couldn't mark inode #%lu dirty (err %d)",
  				inode_bl->i_ino, err);
  			/* Revert all changes: */
  			swap_inode_data(inode, inode_bl);
  			ext4_mark_inode_dirty(handle, inode);
  		}
  	}
393d1d1d7   Dr. Tilmann Bubeck   ext4: implementat...
183
  	ext4_journal_stop(handle);
393d1d1d7   Dr. Tilmann Bubeck   ext4: implementat...
184
  	ext4_double_up_write_data_sem(inode, inode_bl);
30d29b119   Zheng Liu   ext4: fix error p...
185
  journal_err_out:
393d1d1d7   Dr. Tilmann Bubeck   ext4: implementat...
186
187
  	ext4_inode_resume_unlocked_dio(inode);
  	ext4_inode_resume_unlocked_dio(inode_bl);
375e289ea   J. Bruce Fields   vfs: pull ext4's ...
188
  	unlock_two_nondirectories(inode, inode_bl);
393d1d1d7   Dr. Tilmann Bubeck   ext4: implementat...
189
  	iput(inode_bl);
393d1d1d7   Dr. Tilmann Bubeck   ext4: implementat...
190
191
  	return err;
  }
9bd8212f9   Michael Halcrow   ext4 crypto: add ...
192
193
194
195
196
197
198
199
200
  static int uuid_is_zero(__u8 u[16])
  {
  	int	i;
  
  	for (i = 0; i < 16; i++)
  		if (u[i])
  			return 0;
  	return 1;
  }
9b7365fc1   Li Xi   ext4: add FS_IOC_...
201
202
203
204
205
  static int ext4_ioctl_setflags(struct inode *inode,
  			       unsigned int flags)
  {
  	struct ext4_inode_info *ei = EXT4_I(inode);
  	handle_t *handle = NULL;
fdde368e7   Anton Protopopov   ext4: ioctl: fix ...
206
  	int err = -EPERM, migrate = 0;
9b7365fc1   Li Xi   ext4: add FS_IOC_...
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
  	struct ext4_iloc iloc;
  	unsigned int oldflags, mask, i;
  	unsigned int jflag;
  
  	/* Is it quota file? Do not allow user to mess with it */
  	if (IS_NOQUOTA(inode))
  		goto flags_out;
  
  	oldflags = ei->i_flags;
  
  	/* The JOURNAL_DATA flag is modifiable only by root */
  	jflag = flags & EXT4_JOURNAL_DATA_FL;
  
  	/*
  	 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
  	 * the relevant capability.
  	 *
  	 * This test looks nicer. Thanks to Pauline Middelink
  	 */
  	if ((flags ^ oldflags) & (EXT4_APPEND_FL | EXT4_IMMUTABLE_FL)) {
  		if (!capable(CAP_LINUX_IMMUTABLE))
  			goto flags_out;
  	}
  
  	/*
  	 * The JOURNAL_DATA flag can only be changed by
  	 * the relevant capability.
  	 */
  	if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) {
  		if (!capable(CAP_SYS_RESOURCE))
  			goto flags_out;
  	}
  	if ((flags ^ oldflags) & EXT4_EXTENTS_FL)
  		migrate = 1;
  
  	if (flags & EXT4_EOFBLOCKS_FL) {
  		/* we don't support adding EOFBLOCKS flag */
  		if (!(oldflags & EXT4_EOFBLOCKS_FL)) {
  			err = -EOPNOTSUPP;
  			goto flags_out;
  		}
  	} else if (oldflags & EXT4_EOFBLOCKS_FL)
  		ext4_truncate(inode);
  
  	handle = ext4_journal_start(inode, EXT4_HT_INODE, 1);
  	if (IS_ERR(handle)) {
  		err = PTR_ERR(handle);
  		goto flags_out;
  	}
  	if (IS_SYNC(inode))
  		ext4_handle_sync(handle);
  	err = ext4_reserve_inode_write(handle, inode, &iloc);
  	if (err)
  		goto flags_err;
  
  	for (i = 0, mask = 1; i < 32; i++, mask <<= 1) {
  		if (!(mask & EXT4_FL_USER_MODIFIABLE))
  			continue;
  		if (mask & flags)
  			ext4_set_inode_flag(inode, i);
  		else
  			ext4_clear_inode_flag(inode, i);
  	}
  
  	ext4_set_inode_flags(inode);
  	inode->i_ctime = ext4_current_time(inode);
  
  	err = ext4_mark_iloc_dirty(handle, inode, &iloc);
  flags_err:
  	ext4_journal_stop(handle);
  	if (err)
  		goto flags_out;
  
  	if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL))
  		err = ext4_change_inode_journal_flag(inode, jflag);
  	if (err)
  		goto flags_out;
  	if (migrate) {
  		if (flags & EXT4_EXTENTS_FL)
  			err = ext4_ext_migrate(inode);
  		else
  			err = ext4_ind_migrate(inode);
  	}
  
  flags_out:
  	return err;
  }
  
  #ifdef CONFIG_QUOTA
  static int ext4_ioctl_setproject(struct file *filp, __u32 projid)
  {
  	struct inode *inode = file_inode(filp);
  	struct super_block *sb = inode->i_sb;
  	struct ext4_inode_info *ei = EXT4_I(inode);
  	int err, rc;
  	handle_t *handle;
  	kprojid_t kprojid;
  	struct ext4_iloc iloc;
  	struct ext4_inode *raw_inode;
079788d01   Wang Shilong   ext4: fix project...
306
  	struct dquot *transfer_to[MAXQUOTAS] = { };
9b7365fc1   Li Xi   ext4: add FS_IOC_...
307

0b7b77791   Kaho Ng   ext4: remove old ...
308
  	if (!ext4_has_feature_project(sb)) {
9b7365fc1   Li Xi   ext4: add FS_IOC_...
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
  		if (projid != EXT4_DEF_PROJID)
  			return -EOPNOTSUPP;
  		else
  			return 0;
  	}
  
  	if (EXT4_INODE_SIZE(sb) <= EXT4_GOOD_OLD_INODE_SIZE)
  		return -EOPNOTSUPP;
  
  	kprojid = make_kprojid(&init_user_ns, (projid_t)projid);
  
  	if (projid_eq(kprojid, EXT4_I(inode)->i_projid))
  		return 0;
  
  	err = mnt_want_write_file(filp);
  	if (err)
  		return err;
  
  	err = -EPERM;
5955102c9   Al Viro   wrappers for ->i_...
328
  	inode_lock(inode);
9b7365fc1   Li Xi   ext4: add FS_IOC_...
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
  	/* Is it quota file? Do not allow user to mess with it */
  	if (IS_NOQUOTA(inode))
  		goto out_unlock;
  
  	err = ext4_get_inode_loc(inode, &iloc);
  	if (err)
  		goto out_unlock;
  
  	raw_inode = ext4_raw_inode(&iloc);
  	if (!EXT4_FITS_IN_INODE(raw_inode, ei, i_projid)) {
  		err = -EOVERFLOW;
  		brelse(iloc.bh);
  		goto out_unlock;
  	}
  	brelse(iloc.bh);
  
  	dquot_initialize(inode);
  
  	handle = ext4_journal_start(inode, EXT4_HT_QUOTA,
  		EXT4_QUOTA_INIT_BLOCKS(sb) +
  		EXT4_QUOTA_DEL_BLOCKS(sb) + 3);
  	if (IS_ERR(handle)) {
  		err = PTR_ERR(handle);
  		goto out_unlock;
  	}
  
  	err = ext4_reserve_inode_write(handle, inode, &iloc);
  	if (err)
  		goto out_stop;
079788d01   Wang Shilong   ext4: fix project...
358
359
360
361
362
363
  	transfer_to[PRJQUOTA] = dqget(sb, make_kqid_projid(kprojid));
  	if (!IS_ERR(transfer_to[PRJQUOTA])) {
  		err = __dquot_transfer(inode, transfer_to);
  		dqput(transfer_to[PRJQUOTA]);
  		if (err)
  			goto out_dirty;
9b7365fc1   Li Xi   ext4: add FS_IOC_...
364
  	}
079788d01   Wang Shilong   ext4: fix project...
365

9b7365fc1   Li Xi   ext4: add FS_IOC_...
366
367
368
369
370
371
372
373
374
  	EXT4_I(inode)->i_projid = kprojid;
  	inode->i_ctime = ext4_current_time(inode);
  out_dirty:
  	rc = ext4_mark_iloc_dirty(handle, inode, &iloc);
  	if (!err)
  		err = rc;
  out_stop:
  	ext4_journal_stop(handle);
  out_unlock:
5955102c9   Al Viro   wrappers for ->i_...
375
  	inode_unlock(inode);
9b7365fc1   Li Xi   ext4: add FS_IOC_...
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
  	mnt_drop_write_file(filp);
  	return err;
  }
  #else
  static int ext4_ioctl_setproject(struct file *filp, __u32 projid)
  {
  	if (projid != EXT4_DEF_PROJID)
  		return -EOPNOTSUPP;
  	return 0;
  }
  #endif
  
  /* Transfer internal flags to xflags */
  static inline __u32 ext4_iflags_to_xflags(unsigned long iflags)
  {
  	__u32 xflags = 0;
  
  	if (iflags & EXT4_SYNC_FL)
  		xflags |= FS_XFLAG_SYNC;
  	if (iflags & EXT4_IMMUTABLE_FL)
  		xflags |= FS_XFLAG_IMMUTABLE;
  	if (iflags & EXT4_APPEND_FL)
  		xflags |= FS_XFLAG_APPEND;
  	if (iflags & EXT4_NODUMP_FL)
  		xflags |= FS_XFLAG_NODUMP;
  	if (iflags & EXT4_NOATIME_FL)
  		xflags |= FS_XFLAG_NOATIME;
  	if (iflags & EXT4_PROJINHERIT_FL)
  		xflags |= FS_XFLAG_PROJINHERIT;
  	return xflags;
  }
  
  /* Transfer xflags flags to internal */
  static inline unsigned long ext4_xflags_to_iflags(__u32 xflags)
  {
  	unsigned long iflags = 0;
  
  	if (xflags & FS_XFLAG_SYNC)
  		iflags |= EXT4_SYNC_FL;
  	if (xflags & FS_XFLAG_IMMUTABLE)
  		iflags |= EXT4_IMMUTABLE_FL;
  	if (xflags & FS_XFLAG_APPEND)
  		iflags |= EXT4_APPEND_FL;
  	if (xflags & FS_XFLAG_NODUMP)
  		iflags |= EXT4_NODUMP_FL;
  	if (xflags & FS_XFLAG_NOATIME)
  		iflags |= EXT4_NOATIME_FL;
  	if (xflags & FS_XFLAG_PROJINHERIT)
  		iflags |= EXT4_PROJINHERIT_FL;
  
  	return iflags;
  }
5cdd7b2d7   Andi Kleen   Convert ext4 to u...
428
  long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
429
  {
496ad9aa8   Al Viro   new helper: file_...
430
  	struct inode *inode = file_inode(filp);
bab08ab96   Theodore Ts'o   ext4: enforce big...
431
  	struct super_block *sb = inode->i_sb;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
432
  	struct ext4_inode_info *ei = EXT4_I(inode);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
433
  	unsigned int flags;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
434

af5bc92dd   Theodore Ts'o   ext4: Fix whitesp...
435
436
  	ext4_debug("cmd = %u, arg = %lu
  ", cmd, arg);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
437
438
  
  	switch (cmd) {
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
439
  	case EXT4_IOC_GETFLAGS:
ff9ddf7e8   Jan Kara   ext4: copy i_flag...
440
  		ext4_get_inode_flags(ei);
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
441
  		flags = ei->i_flags & EXT4_FL_USER_VISIBLE;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
442
  		return put_user(flags, (int __user *) arg);
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
443
  	case EXT4_IOC_SETFLAGS: {
9b7365fc1   Li Xi   ext4: add FS_IOC_...
444
  		int err;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
445

2e1496707   Serge E. Hallyn   userns: rename is...
446
  		if (!inode_owner_or_capable(inode))
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
447
448
449
450
  			return -EACCES;
  
  		if (get_user(flags, (int __user *) arg))
  			return -EFAULT;
a561be710   Al Viro   switch a bunch of...
451
  		err = mnt_want_write_file(filp);
42a74f206   Dave Hansen   [PATCH] r/o bind ...
452
453
  		if (err)
  			return err;
2dc6b0d48   Duane Griffin   ext4: tighten res...
454
  		flags = ext4_mask_flags(inode->i_mode, flags);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
455

5955102c9   Al Viro   wrappers for ->i_...
456
  		inode_lock(inode);
9b7365fc1   Li Xi   ext4: add FS_IOC_...
457
  		err = ext4_ioctl_setflags(inode, flags);
5955102c9   Al Viro   wrappers for ->i_...
458
  		inode_unlock(inode);
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
459
  		mnt_drop_write_file(filp);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
460
461
  		return err;
  	}
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
462
463
  	case EXT4_IOC_GETVERSION:
  	case EXT4_IOC_GETVERSION_OLD:
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
464
  		return put_user(inode->i_generation, (int __user *) arg);
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
465
466
  	case EXT4_IOC_SETVERSION:
  	case EXT4_IOC_SETVERSION_OLD: {
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
467
  		handle_t *handle;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
468
  		struct ext4_iloc iloc;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
469
470
  		__u32 generation;
  		int err;
2e1496707   Serge E. Hallyn   userns: rename is...
471
  		if (!inode_owner_or_capable(inode))
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
472
  			return -EPERM;
42a74f206   Dave Hansen   [PATCH] r/o bind ...
473

9aa5d32ba   Dmitry Monakhov   ext4: Replace ope...
474
  		if (ext4_has_metadata_csum(inode->i_sb)) {
814525f4d   Darrick J. Wong   ext4: calculate a...
475
476
477
478
  			ext4_warning(sb, "Setting inode version is not "
  				     "supported with metadata_csum enabled.");
  			return -ENOTTY;
  		}
a561be710   Al Viro   switch a bunch of...
479
  		err = mnt_want_write_file(filp);
42a74f206   Dave Hansen   [PATCH] r/o bind ...
480
481
482
483
484
485
  		if (err)
  			return err;
  		if (get_user(generation, (int __user *) arg)) {
  			err = -EFAULT;
  			goto setversion_out;
  		}
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
486

5955102c9   Al Viro   wrappers for ->i_...
487
  		inode_lock(inode);
9924a92a8   Theodore Ts'o   ext4: pass contex...
488
  		handle = ext4_journal_start(inode, EXT4_HT_INODE, 1);
42a74f206   Dave Hansen   [PATCH] r/o bind ...
489
490
  		if (IS_ERR(handle)) {
  			err = PTR_ERR(handle);
6c2155b9c   Djalal Harouni   ext{3,4}: Fix pot...
491
  			goto unlock_out;
42a74f206   Dave Hansen   [PATCH] r/o bind ...
492
  		}
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
493
  		err = ext4_reserve_inode_write(handle, inode, &iloc);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
494
  		if (err == 0) {
ef7f38359   Kalpak Shah   ext4: Add nanosec...
495
  			inode->i_ctime = ext4_current_time(inode);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
496
  			inode->i_generation = generation;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
497
  			err = ext4_mark_iloc_dirty(handle, inode, &iloc);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
498
  		}
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
499
  		ext4_journal_stop(handle);
6c2155b9c   Djalal Harouni   ext{3,4}: Fix pot...
500
501
  
  unlock_out:
5955102c9   Al Viro   wrappers for ->i_...
502
  		inode_unlock(inode);
42a74f206   Dave Hansen   [PATCH] r/o bind ...
503
  setversion_out:
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
504
  		mnt_drop_write_file(filp);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
505
506
  		return err;
  	}
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
507
508
  	case EXT4_IOC_GROUP_EXTEND: {
  		ext4_fsblk_t n_blocks_count;
ac046f1d6   Peng Tao   ext4: fix null ha...
509
  		int err, err2=0;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
510

8f82f840e   Yongqiang Yang   ext4: prevent par...
511
512
513
  		err = ext4_resize_begin(sb);
  		if (err)
  			return err;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
514

014a17703   Djalal Harouni   ext4: add missing...
515
516
517
518
  		if (get_user(n_blocks_count, (__u32 __user *)arg)) {
  			err = -EFAULT;
  			goto group_extend_out;
  		}
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
519

e2b911c53   Darrick J. Wong   ext4: clean up fe...
520
  		if (ext4_has_feature_bigalloc(sb)) {
bab08ab96   Theodore Ts'o   ext4: enforce big...
521
522
  			ext4_msg(sb, KERN_ERR,
  				 "Online resizing not supported with bigalloc");
014a17703   Djalal Harouni   ext4: add missing...
523
524
  			err = -EOPNOTSUPP;
  			goto group_extend_out;
bab08ab96   Theodore Ts'o   ext4: enforce big...
525
  		}
a561be710   Al Viro   switch a bunch of...
526
  		err = mnt_want_write_file(filp);
42a74f206   Dave Hansen   [PATCH] r/o bind ...
527
  		if (err)
014a17703   Djalal Harouni   ext4: add missing...
528
  			goto group_extend_out;
42a74f206   Dave Hansen   [PATCH] r/o bind ...
529

617ba13b3   Mingming Cao   [PATCH] ext4: ren...
530
  		err = ext4_group_extend(sb, EXT4_SB(sb)->s_es, n_blocks_count);
ac046f1d6   Peng Tao   ext4: fix null ha...
531
532
533
534
535
  		if (EXT4_SB(sb)->s_journal) {
  			jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal);
  			err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal);
  			jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
  		}
7ffe1ea89   Hidehiro Kawai   ext4: add checks ...
536
537
  		if (err == 0)
  			err = err2;
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
538
  		mnt_drop_write_file(filp);
014a17703   Djalal Harouni   ext4: add missing...
539
  group_extend_out:
8f82f840e   Yongqiang Yang   ext4: prevent par...
540
  		ext4_resize_end(sb);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
541
542
  		return err;
  	}
748de6736   Akira Fujita   ext4: online defr...
543
544
545
  
  	case EXT4_IOC_MOVE_EXT: {
  		struct move_extent me;
2903ff019   Al Viro   switch simple cas...
546
547
  		struct fd donor;
  		int err;
748de6736   Akira Fujita   ext4: online defr...
548

4a58579b9   Akira Fujita   ext4: Fix insuffi...
549
550
551
  		if (!(filp->f_mode & FMODE_READ) ||
  		    !(filp->f_mode & FMODE_WRITE))
  			return -EBADF;
748de6736   Akira Fujita   ext4: online defr...
552
553
554
  		if (copy_from_user(&me,
  			(struct move_extent __user *)arg, sizeof(me)))
  			return -EFAULT;
4a58579b9   Akira Fujita   ext4: Fix insuffi...
555
  		me.moved_len = 0;
748de6736   Akira Fujita   ext4: online defr...
556

2903ff019   Al Viro   switch simple cas...
557
558
  		donor = fdget(me.donor_fd);
  		if (!donor.file)
748de6736   Akira Fujita   ext4: online defr...
559
  			return -EBADF;
2903ff019   Al Viro   switch simple cas...
560
  		if (!(donor.file->f_mode & FMODE_WRITE)) {
4a58579b9   Akira Fujita   ext4: Fix insuffi...
561
562
  			err = -EBADF;
  			goto mext_out;
748de6736   Akira Fujita   ext4: online defr...
563
  		}
e2b911c53   Darrick J. Wong   ext4: clean up fe...
564
  		if (ext4_has_feature_bigalloc(sb)) {
bab08ab96   Theodore Ts'o   ext4: enforce big...
565
566
  			ext4_msg(sb, KERN_ERR,
  				 "Online defrag not supported with bigalloc");
399c9b862   Al Viro   ext4: close struc...
567
568
  			err = -EOPNOTSUPP;
  			goto mext_out;
73f34a5e2   Ross Zwisler   ext4: online defr...
569
570
571
572
573
  		} else if (IS_DAX(inode)) {
  			ext4_msg(sb, KERN_ERR,
  				 "Online defrag not supported with DAX");
  			err = -EOPNOTSUPP;
  			goto mext_out;
bab08ab96   Theodore Ts'o   ext4: enforce big...
574
  		}
a561be710   Al Viro   switch a bunch of...
575
  		err = mnt_want_write_file(filp);
4a58579b9   Akira Fujita   ext4: Fix insuffi...
576
577
  		if (err)
  			goto mext_out;
2903ff019   Al Viro   switch simple cas...
578
  		err = ext4_move_extents(filp, donor.file, me.orig_start,
748de6736   Akira Fujita   ext4: online defr...
579
  					me.donor_start, me.len, &me.moved_len);
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
580
  		mnt_drop_write_file(filp);
748de6736   Akira Fujita   ext4: online defr...
581

60e6679e2   Theodore Ts'o   ext4: Drop whites...
582
  		if (copy_to_user((struct move_extent __user *)arg,
c437b2733   Akira Fujita   ext4: Code cleanu...
583
  				 &me, sizeof(me)))
4a58579b9   Akira Fujita   ext4: Fix insuffi...
584
585
  			err = -EFAULT;
  mext_out:
2903ff019   Al Viro   switch simple cas...
586
  		fdput(donor);
748de6736   Akira Fujita   ext4: online defr...
587
588
  		return err;
  	}
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
589
590
  	case EXT4_IOC_GROUP_ADD: {
  		struct ext4_new_group_data input;
ac046f1d6   Peng Tao   ext4: fix null ha...
591
  		int err, err2=0;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
592

8f82f840e   Yongqiang Yang   ext4: prevent par...
593
594
595
  		err = ext4_resize_begin(sb);
  		if (err)
  			return err;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
596

617ba13b3   Mingming Cao   [PATCH] ext4: ren...
597
  		if (copy_from_user(&input, (struct ext4_new_group_input __user *)arg,
014a17703   Djalal Harouni   ext4: add missing...
598
599
600
601
  				sizeof(input))) {
  			err = -EFAULT;
  			goto group_add_out;
  		}
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
602

e2b911c53   Darrick J. Wong   ext4: clean up fe...
603
  		if (ext4_has_feature_bigalloc(sb)) {
bab08ab96   Theodore Ts'o   ext4: enforce big...
604
605
  			ext4_msg(sb, KERN_ERR,
  				 "Online resizing not supported with bigalloc");
014a17703   Djalal Harouni   ext4: add missing...
606
607
  			err = -EOPNOTSUPP;
  			goto group_add_out;
bab08ab96   Theodore Ts'o   ext4: enforce big...
608
  		}
a561be710   Al Viro   switch a bunch of...
609
  		err = mnt_want_write_file(filp);
42a74f206   Dave Hansen   [PATCH] r/o bind ...
610
  		if (err)
014a17703   Djalal Harouni   ext4: add missing...
611
  			goto group_add_out;
42a74f206   Dave Hansen   [PATCH] r/o bind ...
612

617ba13b3   Mingming Cao   [PATCH] ext4: ren...
613
  		err = ext4_group_add(sb, &input);
ac046f1d6   Peng Tao   ext4: fix null ha...
614
615
616
617
618
  		if (EXT4_SB(sb)->s_journal) {
  			jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal);
  			err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal);
  			jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
  		}
7ffe1ea89   Hidehiro Kawai   ext4: add checks ...
619
620
  		if (err == 0)
  			err = err2;
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
621
  		mnt_drop_write_file(filp);
7f5118629   Theodore Ts'o   ext4: trigger the...
622
623
624
  		if (!err && ext4_has_group_desc_csum(sb) &&
  		    test_opt(sb, INIT_INODE_TABLE))
  			err = ext4_register_li_request(sb, input.group);
014a17703   Djalal Harouni   ext4: add missing...
625
  group_add_out:
8f82f840e   Yongqiang Yang   ext4: prevent par...
626
  		ext4_resize_end(sb);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
627
628
  		return err;
  	}
c14c6fd5c   Aneesh Kumar K.V   ext4: Add EXT4_IO...
629
  	case EXT4_IOC_MIGRATE:
2a43a8780   Aneesh Kumar K.V   ext4: elevate wri...
630
631
  	{
  		int err;
2e1496707   Serge E. Hallyn   userns: rename is...
632
  		if (!inode_owner_or_capable(inode))
2a43a8780   Aneesh Kumar K.V   ext4: elevate wri...
633
  			return -EACCES;
a561be710   Al Viro   switch a bunch of...
634
  		err = mnt_want_write_file(filp);
2a43a8780   Aneesh Kumar K.V   ext4: elevate wri...
635
636
637
638
639
640
641
642
  		if (err)
  			return err;
  		/*
  		 * inode_mutex prevent write and truncate on the file.
  		 * Read still goes through. We take i_data_sem in
  		 * ext4_ext_swap_inode_data before we switch the
  		 * inode format to prevent read.
  		 */
5955102c9   Al Viro   wrappers for ->i_...
643
  		inode_lock((inode));
2a43a8780   Aneesh Kumar K.V   ext4: elevate wri...
644
  		err = ext4_ext_migrate(inode);
5955102c9   Al Viro   wrappers for ->i_...
645
  		inode_unlock((inode));
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
646
  		mnt_drop_write_file(filp);
2a43a8780   Aneesh Kumar K.V   ext4: elevate wri...
647
648
  		return err;
  	}
c14c6fd5c   Aneesh Kumar K.V   ext4: Add EXT4_IO...
649

ccd2506bd   Theodore Ts'o   ext4: add EXT4_IO...
650
651
652
  	case EXT4_IOC_ALLOC_DA_BLKS:
  	{
  		int err;
2e1496707   Serge E. Hallyn   userns: rename is...
653
  		if (!inode_owner_or_capable(inode))
ccd2506bd   Theodore Ts'o   ext4: add EXT4_IO...
654
  			return -EACCES;
a561be710   Al Viro   switch a bunch of...
655
  		err = mnt_want_write_file(filp);
ccd2506bd   Theodore Ts'o   ext4: add EXT4_IO...
656
657
658
  		if (err)
  			return err;
  		err = ext4_alloc_da_blocks(inode);
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
659
  		mnt_drop_write_file(filp);
ccd2506bd   Theodore Ts'o   ext4: add EXT4_IO...
660
661
  		return err;
  	}
393d1d1d7   Dr. Tilmann Bubeck   ext4: implementat...
662
  	case EXT4_IOC_SWAP_BOOT:
3e67cfad2   Dmitry Monakhov   ext4: grab missed...
663
664
  	{
  		int err;
393d1d1d7   Dr. Tilmann Bubeck   ext4: implementat...
665
666
  		if (!(filp->f_mode & FMODE_WRITE))
  			return -EBADF;
3e67cfad2   Dmitry Monakhov   ext4: grab missed...
667
668
669
670
671
672
673
  		err = mnt_want_write_file(filp);
  		if (err)
  			return err;
  		err = swap_inode_boot_loader(sb, inode);
  		mnt_drop_write_file(filp);
  		return err;
  	}
393d1d1d7   Dr. Tilmann Bubeck   ext4: implementat...
674

19c5246d2   Yongqiang Yang   ext4: add new onl...
675
676
  	case EXT4_IOC_RESIZE_FS: {
  		ext4_fsblk_t n_blocks_count;
19c5246d2   Yongqiang Yang   ext4: add new onl...
677
  		int err = 0, err2 = 0;
7f5118629   Theodore Ts'o   ext4: trigger the...
678
  		ext4_group_t o_group = EXT4_SB(sb)->s_groups_count;
19c5246d2   Yongqiang Yang   ext4: add new onl...
679

e2b911c53   Darrick J. Wong   ext4: clean up fe...
680
  		if (ext4_has_feature_bigalloc(sb)) {
19c5246d2   Yongqiang Yang   ext4: add new onl...
681
682
683
684
  			ext4_msg(sb, KERN_ERR,
  				 "Online resizing not (yet) supported with bigalloc");
  			return -EOPNOTSUPP;
  		}
19c5246d2   Yongqiang Yang   ext4: add new onl...
685
686
687
688
  		if (copy_from_user(&n_blocks_count, (__u64 __user *)arg,
  				   sizeof(__u64))) {
  			return -EFAULT;
  		}
19c5246d2   Yongqiang Yang   ext4: add new onl...
689
690
691
  		err = ext4_resize_begin(sb);
  		if (err)
  			return err;
8cae6f715   Al Viro   ext4: switch EXT4...
692
  		err = mnt_want_write_file(filp);
19c5246d2   Yongqiang Yang   ext4: add new onl...
693
694
695
696
697
698
699
700
701
702
703
  		if (err)
  			goto resizefs_out;
  
  		err = ext4_resize_fs(sb, n_blocks_count);
  		if (EXT4_SB(sb)->s_journal) {
  			jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal);
  			err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal);
  			jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
  		}
  		if (err == 0)
  			err = err2;
8cae6f715   Al Viro   ext4: switch EXT4...
704
  		mnt_drop_write_file(filp);
7f5118629   Theodore Ts'o   ext4: trigger the...
705
706
707
708
  		if (!err && (o_group > EXT4_SB(sb)->s_groups_count) &&
  		    ext4_has_group_desc_csum(sb) &&
  		    test_opt(sb, INIT_INODE_TABLE))
  			err = ext4_register_li_request(sb, o_group);
19c5246d2   Yongqiang Yang   ext4: add new onl...
709
710
711
712
  resizefs_out:
  		ext4_resize_end(sb);
  		return err;
  	}
e681c047e   Lukas Czerner   ext4: Add EXT4_IO...
713
714
  	case FITRIM:
  	{
414317921   Lukas Czerner   ext4: check if de...
715
  		struct request_queue *q = bdev_get_queue(sb->s_bdev);
e681c047e   Lukas Czerner   ext4: Add EXT4_IO...
716
717
718
719
720
  		struct fstrim_range range;
  		int ret = 0;
  
  		if (!capable(CAP_SYS_ADMIN))
  			return -EPERM;
414317921   Lukas Czerner   ext4: check if de...
721
722
  		if (!blk_queue_discard(q))
  			return -EOPNOTSUPP;
e6705f7c2   H Hartley Sweeten   ext4: add __user ...
723
  		if (copy_from_user(&range, (struct fstrim_range __user *)arg,
e681c047e   Lukas Czerner   ext4: Add EXT4_IO...
724
725
  		    sizeof(range)))
  			return -EFAULT;
5c2ed62fd   Lukas Czerner   ext4: Adjust minl...
726
727
  		range.minlen = max((unsigned int)range.minlen,
  				   q->limits.discard_granularity);
e681c047e   Lukas Czerner   ext4: Add EXT4_IO...
728
729
730
  		ret = ext4_trim_fs(sb, &range);
  		if (ret < 0)
  			return ret;
e6705f7c2   H Hartley Sweeten   ext4: add __user ...
731
  		if (copy_to_user((struct fstrim_range __user *)arg, &range,
e681c047e   Lukas Czerner   ext4: Add EXT4_IO...
732
733
734
735
736
  		    sizeof(range)))
  			return -EFAULT;
  
  		return 0;
  	}
7869a4a6c   Theodore Ts'o   ext4: add support...
737
738
  	case EXT4_IOC_PRECACHE_EXTENTS:
  		return ext4_ext_precache(inode);
9bd8212f9   Michael Halcrow   ext4 crypto: add ...
739
740
  	case EXT4_IOC_SET_ENCRYPTION_POLICY: {
  #ifdef CONFIG_EXT4_FS_ENCRYPTION
a7550b30a   Jaegeuk Kim   ext4 crypto: migr...
741
  		struct fscrypt_policy policy;
9bd8212f9   Michael Halcrow   ext4 crypto: add ...
742

9a200d075   Richard Weinberger   ext4: require enc...
743
744
  		if (!ext4_has_feature_encrypt(sb))
  			return -EOPNOTSUPP;
9bd8212f9   Michael Halcrow   ext4 crypto: add ...
745
  		if (copy_from_user(&policy,
a7550b30a   Jaegeuk Kim   ext4 crypto: migr...
746
747
748
  				   (struct fscrypt_policy __user *)arg,
  				   sizeof(policy)))
  			return -EFAULT;
ba63f23d6   Eric Biggers   fscrypto: require...
749
  		return fscrypt_process_policy(filp, &policy);
9bd8212f9   Michael Halcrow   ext4 crypto: add ...
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
  #else
  		return -EOPNOTSUPP;
  #endif
  	}
  	case EXT4_IOC_GET_ENCRYPTION_PWSALT: {
  		int err, err2;
  		struct ext4_sb_info *sbi = EXT4_SB(sb);
  		handle_t *handle;
  
  		if (!ext4_sb_has_crypto(sb))
  			return -EOPNOTSUPP;
  		if (uuid_is_zero(sbi->s_es->s_encrypt_pw_salt)) {
  			err = mnt_want_write_file(filp);
  			if (err)
  				return err;
  			handle = ext4_journal_start_sb(sb, EXT4_HT_MISC, 1);
  			if (IS_ERR(handle)) {
  				err = PTR_ERR(handle);
  				goto pwsalt_err_exit;
  			}
  			err = ext4_journal_get_write_access(handle, sbi->s_sbh);
  			if (err)
  				goto pwsalt_err_journal;
  			generate_random_uuid(sbi->s_es->s_encrypt_pw_salt);
  			err = ext4_handle_dirty_metadata(handle, NULL,
  							 sbi->s_sbh);
  		pwsalt_err_journal:
  			err2 = ext4_journal_stop(handle);
  			if (err2 && !err)
  				err = err2;
  		pwsalt_err_exit:
  			mnt_drop_write_file(filp);
  			if (err)
  				return err;
  		}
b4ab9e298   Fabian Frederick   ext4 crypto: fix ...
785
786
  		if (copy_to_user((void __user *) arg,
  				 sbi->s_es->s_encrypt_pw_salt, 16))
9bd8212f9   Michael Halcrow   ext4 crypto: add ...
787
788
789
790
791
  			return -EFAULT;
  		return 0;
  	}
  	case EXT4_IOC_GET_ENCRYPTION_POLICY: {
  #ifdef CONFIG_EXT4_FS_ENCRYPTION
a7550b30a   Jaegeuk Kim   ext4 crypto: migr...
792
  		struct fscrypt_policy policy;
9bd8212f9   Michael Halcrow   ext4 crypto: add ...
793
794
795
796
  		int err = 0;
  
  		if (!ext4_encrypted_inode(inode))
  			return -ENOENT;
a7550b30a   Jaegeuk Kim   ext4 crypto: migr...
797
  		err = fscrypt_get_policy(inode, &policy);
9bd8212f9   Michael Halcrow   ext4 crypto: add ...
798
799
  		if (err)
  			return err;
b4ab9e298   Fabian Frederick   ext4 crypto: fix ...
800
  		if (copy_to_user((void __user *)arg, &policy, sizeof(policy)))
9bd8212f9   Michael Halcrow   ext4 crypto: add ...
801
802
803
804
805
806
  			return -EFAULT;
  		return 0;
  #else
  		return -EOPNOTSUPP;
  #endif
  	}
9b7365fc1   Li Xi   ext4: add FS_IOC_...
807
808
809
810
811
812
813
  	case EXT4_IOC_FSGETXATTR:
  	{
  		struct fsxattr fa;
  
  		memset(&fa, 0, sizeof(struct fsxattr));
  		ext4_get_inode_flags(ei);
  		fa.fsx_xflags = ext4_iflags_to_xflags(ei->i_flags & EXT4_FL_USER_VISIBLE);
0b7b77791   Kaho Ng   ext4: remove old ...
814
  		if (ext4_has_feature_project(inode->i_sb)) {
9b7365fc1   Li Xi   ext4: add FS_IOC_...
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
  			fa.fsx_projid = (__u32)from_kprojid(&init_user_ns,
  				EXT4_I(inode)->i_projid);
  		}
  
  		if (copy_to_user((struct fsxattr __user *)arg,
  				 &fa, sizeof(fa)))
  			return -EFAULT;
  		return 0;
  	}
  	case EXT4_IOC_FSSETXATTR:
  	{
  		struct fsxattr fa;
  		int err;
  
  		if (copy_from_user(&fa, (struct fsxattr __user *)arg,
  				   sizeof(fa)))
  			return -EFAULT;
  
  		/* Make sure caller has proper permission */
  		if (!inode_owner_or_capable(inode))
  			return -EACCES;
  
  		err = mnt_want_write_file(filp);
  		if (err)
  			return err;
  
  		flags = ext4_xflags_to_iflags(fa.fsx_xflags);
  		flags = ext4_mask_flags(inode->i_mode, flags);
5955102c9   Al Viro   wrappers for ->i_...
843
  		inode_lock(inode);
9b7365fc1   Li Xi   ext4: add FS_IOC_...
844
845
846
  		flags = (ei->i_flags & ~EXT4_FL_XFLAG_VISIBLE) |
  			 (flags & EXT4_FL_XFLAG_VISIBLE);
  		err = ext4_ioctl_setflags(inode, flags);
5955102c9   Al Viro   wrappers for ->i_...
847
  		inode_unlock(inode);
9b7365fc1   Li Xi   ext4: add FS_IOC_...
848
849
850
851
852
853
854
855
856
857
  		mnt_drop_write_file(filp);
  		if (err)
  			return err;
  
  		err = ext4_ioctl_setproject(filp, fa.fsx_projid);
  		if (err)
  			return err;
  
  		return 0;
  	}
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
858
859
860
861
862
863
  	default:
  		return -ENOTTY;
  	}
  }
  
  #ifdef CONFIG_COMPAT
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
864
  long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
865
  {
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
866
867
  	/* These are just misnamed, they actually get/put from/to user an int */
  	switch (cmd) {
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
868
869
  	case EXT4_IOC32_GETFLAGS:
  		cmd = EXT4_IOC_GETFLAGS;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
870
  		break;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
871
872
  	case EXT4_IOC32_SETFLAGS:
  		cmd = EXT4_IOC_SETFLAGS;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
873
  		break;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
874
875
  	case EXT4_IOC32_GETVERSION:
  		cmd = EXT4_IOC_GETVERSION;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
876
  		break;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
877
878
  	case EXT4_IOC32_SETVERSION:
  		cmd = EXT4_IOC_SETVERSION;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
879
  		break;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
880
881
  	case EXT4_IOC32_GROUP_EXTEND:
  		cmd = EXT4_IOC_GROUP_EXTEND;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
882
  		break;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
883
884
  	case EXT4_IOC32_GETVERSION_OLD:
  		cmd = EXT4_IOC_GETVERSION_OLD;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
885
  		break;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
886
887
  	case EXT4_IOC32_SETVERSION_OLD:
  		cmd = EXT4_IOC_SETVERSION_OLD;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
888
  		break;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
889
890
  	case EXT4_IOC32_GETRSVSZ:
  		cmd = EXT4_IOC_GETRSVSZ;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
891
  		break;
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
892
893
  	case EXT4_IOC32_SETRSVSZ:
  		cmd = EXT4_IOC_SETRSVSZ;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
894
  		break;
4d92dc0f0   Ben Hutchings   ext4: Fix compat ...
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
  	case EXT4_IOC32_GROUP_ADD: {
  		struct compat_ext4_new_group_input __user *uinput;
  		struct ext4_new_group_input input;
  		mm_segment_t old_fs;
  		int err;
  
  		uinput = compat_ptr(arg);
  		err = get_user(input.group, &uinput->group);
  		err |= get_user(input.block_bitmap, &uinput->block_bitmap);
  		err |= get_user(input.inode_bitmap, &uinput->inode_bitmap);
  		err |= get_user(input.inode_table, &uinput->inode_table);
  		err |= get_user(input.blocks_count, &uinput->blocks_count);
  		err |= get_user(input.reserved_blocks,
  				&uinput->reserved_blocks);
  		if (err)
  			return -EFAULT;
  		old_fs = get_fs();
  		set_fs(KERNEL_DS);
  		err = ext4_ioctl(file, EXT4_IOC_GROUP_ADD,
  				 (unsigned long) &input);
  		set_fs(old_fs);
  		return err;
  	}
b684b2ee9   Christian Borntraeger   ext4: allow defra...
918
  	case EXT4_IOC_MOVE_EXT:
19c5246d2   Yongqiang Yang   ext4: add new onl...
919
  	case EXT4_IOC_RESIZE_FS:
7869a4a6c   Theodore Ts'o   ext4: add support...
920
  	case EXT4_IOC_PRECACHE_EXTENTS:
9bd8212f9   Michael Halcrow   ext4 crypto: add ...
921
922
923
  	case EXT4_IOC_SET_ENCRYPTION_POLICY:
  	case EXT4_IOC_GET_ENCRYPTION_PWSALT:
  	case EXT4_IOC_GET_ENCRYPTION_POLICY:
b684b2ee9   Christian Borntraeger   ext4: allow defra...
924
  		break;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
925
926
927
  	default:
  		return -ENOIOCTLCMD;
  	}
5cdd7b2d7   Andi Kleen   Convert ext4 to u...
928
  	return ext4_ioctl(file, cmd, (unsigned long) compat_ptr(arg));
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
929
930
  }
  #endif