Blame view

fs/ext3/ioctl.c 7.58 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
  /*
   * linux/fs/ext3/ioctl.c
   *
   * 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>
  #include <linux/jbd.h>
16f7e0fe2   Randy Dunlap   [PATCH] capable/c...
12
  #include <linux/capability.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
13
14
  #include <linux/ext3_fs.h>
  #include <linux/ext3_jbd.h>
42a74f206   Dave Hansen   [PATCH] r/o bind ...
15
  #include <linux/mount.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16
  #include <linux/time.h>
52a700c56   David Howells   [PATCH] BLOCK: Mo...
17
  #include <linux/compat.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
  #include <asm/uaccess.h>
039fd8ce6   Cyrus Massoumi   ext3: remove the ...
19
  long ext3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
  {
039fd8ce6   Cyrus Massoumi   ext3: remove the ...
21
  	struct inode *inode = filp->f_dentry->d_inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
23
24
25
26
27
28
29
30
  	struct ext3_inode_info *ei = EXT3_I(inode);
  	unsigned int flags;
  	unsigned short rsv_window_size;
  
  	ext3_debug ("cmd = %u, arg = %lu
  ", cmd, arg);
  
  	switch (cmd) {
  	case EXT3_IOC_GETFLAGS:
28be5abb4   Jan Kara   ext3: copy i_flag...
31
  		ext3_get_inode_flags(ei);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
33
34
35
36
37
38
39
  		flags = ei->i_flags & EXT3_FL_USER_VISIBLE;
  		return put_user(flags, (int __user *) arg);
  	case EXT3_IOC_SETFLAGS: {
  		handle_t *handle = NULL;
  		int err;
  		struct ext3_iloc iloc;
  		unsigned int oldflags;
  		unsigned int jflag;
2e1496707   Serge E. Hallyn   userns: rename is...
40
  		if (!inode_owner_or_capable(inode))
039fd8ce6   Cyrus Massoumi   ext3: remove the ...
41
42
43
44
  			return -EACCES;
  
  		if (get_user(flags, (int __user *) arg))
  			return -EFAULT;
a561be710   Al Viro   switch a bunch of...
45
  		err = mnt_want_write_file(filp);
42a74f206   Dave Hansen   [PATCH] r/o bind ...
46
47
  		if (err)
  			return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48

04143e2fb   Duane Griffin   ext3: tighten res...
49
  		flags = ext3_mask_flags(inode->i_mode, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50

a090d9132   Al Viro   [PATCH] protect e...
51
  		mutex_lock(&inode->i_mutex);
039fd8ce6   Cyrus Massoumi   ext3: remove the ...
52

e47776a0a   Jan Kara   Forbid user to ch...
53
  		/* Is it quota file? Do not allow user to mess with it */
039fd8ce6   Cyrus Massoumi   ext3: remove the ...
54
55
  		err = -EPERM;
  		if (IS_NOQUOTA(inode))
42a74f206   Dave Hansen   [PATCH] r/o bind ...
56
  			goto flags_out;
039fd8ce6   Cyrus Massoumi   ext3: remove the ...
57

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
59
60
61
62
63
64
65
66
67
68
69
  		oldflags = ei->i_flags;
  
  		/* The JOURNAL_DATA flag is modifiable only by root */
  		jflag = flags & EXT3_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) & (EXT3_APPEND_FL | EXT3_IMMUTABLE_FL)) {
039fd8ce6   Cyrus Massoumi   ext3: remove the ...
70
  			if (!capable(CAP_LINUX_IMMUTABLE))
42a74f206   Dave Hansen   [PATCH] r/o bind ...
71
  				goto flags_out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72
73
74
75
76
77
78
  		}
  
  		/*
  		 * The JOURNAL_DATA flag can only be changed by
  		 * the relevant capability.
  		 */
  		if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL)) {
039fd8ce6   Cyrus Massoumi   ext3: remove the ...
79
  			if (!capable(CAP_SYS_RESOURCE))
42a74f206   Dave Hansen   [PATCH] r/o bind ...
80
  				goto flags_out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
81
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
82
  		handle = ext3_journal_start(inode, 1);
a090d9132   Al Viro   [PATCH] protect e...
83
  		if (IS_ERR(handle)) {
42a74f206   Dave Hansen   [PATCH] r/o bind ...
84
85
  			err = PTR_ERR(handle);
  			goto flags_out;
a090d9132   Al Viro   [PATCH] protect e...
86
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
  		if (IS_SYNC(inode))
  			handle->h_sync = 1;
  		err = ext3_reserve_inode_write(handle, inode, &iloc);
  		if (err)
  			goto flags_err;
  
  		flags = flags & EXT3_FL_USER_MODIFIABLE;
  		flags |= oldflags & ~EXT3_FL_USER_MODIFIABLE;
  		ei->i_flags = flags;
  
  		ext3_set_inode_flags(inode);
  		inode->i_ctime = CURRENT_TIME_SEC;
  
  		err = ext3_mark_iloc_dirty(handle, inode, &iloc);
  flags_err:
  		ext3_journal_stop(handle);
039fd8ce6   Cyrus Massoumi   ext3: remove the ...
103
104
  		if (err)
  			goto flags_out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
105
106
107
  
  		if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL))
  			err = ext3_change_inode_journal_flag(inode, jflag);
42a74f206   Dave Hansen   [PATCH] r/o bind ...
108
  flags_out:
039fd8ce6   Cyrus Massoumi   ext3: remove the ...
109
  		mutex_unlock(&inode->i_mutex);
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
110
  		mnt_drop_write_file(filp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
112
113
114
115
116
117
118
119
120
121
  		return err;
  	}
  	case EXT3_IOC_GETVERSION:
  	case EXT3_IOC_GETVERSION_OLD:
  		return put_user(inode->i_generation, (int __user *) arg);
  	case EXT3_IOC_SETVERSION:
  	case EXT3_IOC_SETVERSION_OLD: {
  		handle_t *handle;
  		struct ext3_iloc iloc;
  		__u32 generation;
  		int err;
2e1496707   Serge E. Hallyn   userns: rename is...
122
  		if (!inode_owner_or_capable(inode))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
123
  			return -EPERM;
039fd8ce6   Cyrus Massoumi   ext3: remove the ...
124

a561be710   Al Viro   switch a bunch of...
125
  		err = mnt_want_write_file(filp);
42a74f206   Dave Hansen   [PATCH] r/o bind ...
126
127
128
129
130
131
  		if (err)
  			return err;
  		if (get_user(generation, (int __user *) arg)) {
  			err = -EFAULT;
  			goto setversion_out;
  		}
039fd8ce6   Cyrus Massoumi   ext3: remove the ...
132

6c2155b9c   Djalal Harouni   ext{3,4}: Fix pot...
133
  		mutex_lock(&inode->i_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134
  		handle = ext3_journal_start(inode, 1);
42a74f206   Dave Hansen   [PATCH] r/o bind ...
135
136
  		if (IS_ERR(handle)) {
  			err = PTR_ERR(handle);
6c2155b9c   Djalal Harouni   ext{3,4}: Fix pot...
137
  			goto unlock_out;
42a74f206   Dave Hansen   [PATCH] r/o bind ...
138
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139
140
141
142
143
144
145
  		err = ext3_reserve_inode_write(handle, inode, &iloc);
  		if (err == 0) {
  			inode->i_ctime = CURRENT_TIME_SEC;
  			inode->i_generation = generation;
  			err = ext3_mark_iloc_dirty(handle, inode, &iloc);
  		}
  		ext3_journal_stop(handle);
6c2155b9c   Djalal Harouni   ext{3,4}: Fix pot...
146
147
148
  
  unlock_out:
  		mutex_unlock(&inode->i_mutex);
42a74f206   Dave Hansen   [PATCH] r/o bind ...
149
  setversion_out:
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
150
  		mnt_drop_write_file(filp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
151
152
  		return err;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
153
154
155
156
157
158
159
160
161
  	case EXT3_IOC_GETRSVSZ:
  		if (test_opt(inode->i_sb, RESERVATION)
  			&& S_ISREG(inode->i_mode)
  			&& ei->i_block_alloc_info) {
  			rsv_window_size = ei->i_block_alloc_info->rsv_window_node.rsv_goal_size;
  			return put_user(rsv_window_size, (int __user *)arg);
  		}
  		return -ENOTTY;
  	case EXT3_IOC_SETRSVSZ: {
42a74f206   Dave Hansen   [PATCH] r/o bind ...
162
  		int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
164
165
  
  		if (!test_opt(inode->i_sb, RESERVATION) ||!S_ISREG(inode->i_mode))
  			return -ENOTTY;
a561be710   Al Viro   switch a bunch of...
166
  		err = mnt_want_write_file(filp);
42a74f206   Dave Hansen   [PATCH] r/o bind ...
167
168
  		if (err)
  			return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
169

2e1496707   Serge E. Hallyn   userns: rename is...
170
  		if (!inode_owner_or_capable(inode)) {
42a74f206   Dave Hansen   [PATCH] r/o bind ...
171
172
173
  			err = -EACCES;
  			goto setrsvsz_out;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
174

42a74f206   Dave Hansen   [PATCH] r/o bind ...
175
176
177
178
  		if (get_user(rsv_window_size, (int __user *)arg)) {
  			err = -EFAULT;
  			goto setrsvsz_out;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179
180
181
182
183
184
185
186
  
  		if (rsv_window_size > EXT3_MAX_RESERVE_BLOCKS)
  			rsv_window_size = EXT3_MAX_RESERVE_BLOCKS;
  
  		/*
  		 * need to allocate reservation structure for this inode
  		 * before set the window size
  		 */
974615186   Arjan van de Ven   [PATCH] convert e...
187
  		mutex_lock(&ei->truncate_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
188
189
190
191
192
193
194
  		if (!ei->i_block_alloc_info)
  			ext3_init_block_alloc_info(inode);
  
  		if (ei->i_block_alloc_info){
  			struct ext3_reserve_window_node *rsv = &ei->i_block_alloc_info->rsv_window_node;
  			rsv->rsv_goal_size = rsv_window_size;
  		}
974615186   Arjan van de Ven   [PATCH] convert e...
195
  		mutex_unlock(&ei->truncate_mutex);
42a74f206   Dave Hansen   [PATCH] r/o bind ...
196
  setrsvsz_out:
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
197
  		mnt_drop_write_file(filp);
42a74f206   Dave Hansen   [PATCH] r/o bind ...
198
  		return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199
200
  	}
  	case EXT3_IOC_GROUP_EXTEND: {
43d23f903   Mingming Cao   [PATCH] ext3_fsbl...
201
  		ext3_fsblk_t n_blocks_count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
202
  		struct super_block *sb = inode->i_sb;
2d7c820e5   Hidehiro Kawai   ext3: add checks ...
203
  		int err, err2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
204
205
206
  
  		if (!capable(CAP_SYS_RESOURCE))
  			return -EPERM;
a561be710   Al Viro   switch a bunch of...
207
  		err = mnt_want_write_file(filp);
42a74f206   Dave Hansen   [PATCH] r/o bind ...
208
209
  		if (err)
  			return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
210

42a74f206   Dave Hansen   [PATCH] r/o bind ...
211
212
213
214
  		if (get_user(n_blocks_count, (__u32 __user *)arg)) {
  			err = -EFAULT;
  			goto group_extend_out;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
215
216
  		err = ext3_group_extend(sb, EXT3_SB(sb)->s_es, n_blocks_count);
  		journal_lock_updates(EXT3_SB(sb)->s_journal);
2d7c820e5   Hidehiro Kawai   ext3: add checks ...
217
  		err2 = journal_flush(EXT3_SB(sb)->s_journal);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
218
  		journal_unlock_updates(EXT3_SB(sb)->s_journal);
2d7c820e5   Hidehiro Kawai   ext3: add checks ...
219
220
  		if (err == 0)
  			err = err2;
42a74f206   Dave Hansen   [PATCH] r/o bind ...
221
  group_extend_out:
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
222
  		mnt_drop_write_file(filp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
223
224
225
226
227
  		return err;
  	}
  	case EXT3_IOC_GROUP_ADD: {
  		struct ext3_new_group_data input;
  		struct super_block *sb = inode->i_sb;
2d7c820e5   Hidehiro Kawai   ext3: add checks ...
228
  		int err, err2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
229
230
231
  
  		if (!capable(CAP_SYS_RESOURCE))
  			return -EPERM;
a561be710   Al Viro   switch a bunch of...
232
  		err = mnt_want_write_file(filp);
42a74f206   Dave Hansen   [PATCH] r/o bind ...
233
234
  		if (err)
  			return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
235
236
  
  		if (copy_from_user(&input, (struct ext3_new_group_input __user *)arg,
42a74f206   Dave Hansen   [PATCH] r/o bind ...
237
238
239
240
  				sizeof(input))) {
  			err = -EFAULT;
  			goto group_add_out;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
241
242
243
  
  		err = ext3_group_add(sb, &input);
  		journal_lock_updates(EXT3_SB(sb)->s_journal);
2d7c820e5   Hidehiro Kawai   ext3: add checks ...
244
  		err2 = journal_flush(EXT3_SB(sb)->s_journal);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
245
  		journal_unlock_updates(EXT3_SB(sb)->s_journal);
2d7c820e5   Hidehiro Kawai   ext3: add checks ...
246
247
  		if (err == 0)
  			err = err2;
42a74f206   Dave Hansen   [PATCH] r/o bind ...
248
  group_add_out:
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
249
  		mnt_drop_write_file(filp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
250
251
  		return err;
  	}
9c5274923   Lukas Czerner   ext3: Add FITRIM ...
252
  	case FITRIM: {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
253

9c5274923   Lukas Czerner   ext3: Add FITRIM ...
254
255
256
257
258
259
  		struct super_block *sb = inode->i_sb;
  		struct fstrim_range range;
  		int ret = 0;
  
  		if (!capable(CAP_SYS_ADMIN))
  			return -EPERM;
81fe8c62f   H Hartley Sweeten   ext3/ioctl.c: sil...
260
  		if (copy_from_user(&range, (struct fstrim_range __user *)arg,
9c5274923   Lukas Czerner   ext3: Add FITRIM ...
261
262
263
264
265
266
  				   sizeof(range)))
  			return -EFAULT;
  
  		ret = ext3_trim_fs(sb, &range);
  		if (ret < 0)
  			return ret;
81fe8c62f   H Hartley Sweeten   ext3/ioctl.c: sil...
267
  		if (copy_to_user((struct fstrim_range __user *)arg, &range,
9c5274923   Lukas Czerner   ext3: Add FITRIM ...
268
269
270
271
272
  				 sizeof(range)))
  			return -EFAULT;
  
  		return 0;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
273
274
275
276
277
  
  	default:
  		return -ENOTTY;
  	}
  }
52a700c56   David Howells   [PATCH] BLOCK: Mo...
278
279
280
281
  
  #ifdef CONFIG_COMPAT
  long ext3_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  {
52a700c56   David Howells   [PATCH] BLOCK: Mo...
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
  	/* These are just misnamed, they actually get/put from/to user an int */
  	switch (cmd) {
  	case EXT3_IOC32_GETFLAGS:
  		cmd = EXT3_IOC_GETFLAGS;
  		break;
  	case EXT3_IOC32_SETFLAGS:
  		cmd = EXT3_IOC_SETFLAGS;
  		break;
  	case EXT3_IOC32_GETVERSION:
  		cmd = EXT3_IOC_GETVERSION;
  		break;
  	case EXT3_IOC32_SETVERSION:
  		cmd = EXT3_IOC_SETVERSION;
  		break;
  	case EXT3_IOC32_GROUP_EXTEND:
  		cmd = EXT3_IOC_GROUP_EXTEND;
  		break;
  	case EXT3_IOC32_GETVERSION_OLD:
  		cmd = EXT3_IOC_GETVERSION_OLD;
  		break;
  	case EXT3_IOC32_SETVERSION_OLD:
  		cmd = EXT3_IOC_SETVERSION_OLD;
  		break;
  #ifdef CONFIG_JBD_DEBUG
  	case EXT3_IOC32_WAIT_FOR_READONLY:
  		cmd = EXT3_IOC_WAIT_FOR_READONLY;
  		break;
  #endif
  	case EXT3_IOC32_GETRSVSZ:
  		cmd = EXT3_IOC_GETRSVSZ;
  		break;
  	case EXT3_IOC32_SETRSVSZ:
  		cmd = EXT3_IOC_SETRSVSZ;
  		break;
  	case EXT3_IOC_GROUP_ADD:
  		break;
  	default:
  		return -ENOIOCTLCMD;
  	}
039fd8ce6   Cyrus Massoumi   ext3: remove the ...
321
  	return ext3_ioctl(file, cmd, (unsigned long) compat_ptr(arg));
52a700c56   David Howells   [PATCH] BLOCK: Mo...
322
323
  }
  #endif