1 /* 2 * linux/fs/ext4/ioctl.c 3 * 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> 11 #include <linux/jbd2.h> 12 #include <linux/capability.h> 13 #include <linux/time.h> 14 #include <linux/compat.h> 15 #include <linux/mount.h> 16 #include <linux/file.h> 17 #include <asm/uaccess.h> 18 #include "ext4_jbd2.h" 19 #include "ext4.h" 20 21 long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 22 { 23 struct inode *inode = filp->f_dentry->d_inode; 24 struct ext4_inode_info *ei = EXT4_I(inode); 25 unsigned int flags; 26 27 ext4_debug("cmd = %u, arg = %lu\n", cmd, arg); 28 29 switch (cmd) { 30 case EXT4_IOC_GETFLAGS: 31 ext4_get_inode_flags(ei); 32 flags = ei->i_flags & EXT4_FL_USER_VISIBLE; 33 return put_user(flags, (int __user *) arg); 34 case EXT4_IOC_SETFLAGS: { 35 handle_t *handle = NULL; 36 int err, migrate = 0; 37 struct ext4_iloc iloc; 38 unsigned int oldflags; 39 unsigned int jflag; 40 41 if (!inode_owner_or_capable(inode)) 42 return -EACCES; 43 44 if (get_user(flags, (int __user *) arg)) 45 return -EFAULT; 46 47 err = mnt_want_write(filp->f_path.mnt); 48 if (err) 49 return err; 50 51 flags = ext4_mask_flags(inode->i_mode, flags); 52 53 err = -EPERM; 54 mutex_lock(&inode->i_mutex); 55 /* Is it quota file? Do not allow user to mess with it */ 56 if (IS_NOQUOTA(inode)) 57 goto flags_out; 58 59 oldflags = ei->i_flags; 60 61 /* The JOURNAL_DATA flag is modifiable only by root */ 62 jflag = flags & EXT4_JOURNAL_DATA_FL; 63 64 /* 65 * The IMMUTABLE and APPEND_ONLY flags can only be changed by 66 * the relevant capability. 67 * 68 * This test looks nicer. Thanks to Pauline Middelink 69 */ 70 if ((flags ^ oldflags) & (EXT4_APPEND_FL | EXT4_IMMUTABLE_FL)) { 71 if (!capable(CAP_LINUX_IMMUTABLE)) 72 goto flags_out; 73 } 74 75 /* 76 * The JOURNAL_DATA flag can only be changed by 77 * the relevant capability. 78 */ 79 if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) { 80 if (!capable(CAP_SYS_RESOURCE)) 81 goto flags_out; 82 } 83 if (oldflags & EXT4_EXTENTS_FL) { 84 /* We don't support clearning extent flags */ 85 if (!(flags & EXT4_EXTENTS_FL)) { 86 err = -EOPNOTSUPP; 87 goto flags_out; 88 } 89 } else if (flags & EXT4_EXTENTS_FL) { 90 /* migrate the file */ 91 migrate = 1; 92 flags &= ~EXT4_EXTENTS_FL; 93 } 94 95 if (flags & EXT4_EOFBLOCKS_FL) { 96 /* we don't support adding EOFBLOCKS flag */ 97 if (!(oldflags & EXT4_EOFBLOCKS_FL)) { 98 err = -EOPNOTSUPP; 99 goto flags_out; 100 } 101 } else if (oldflags & EXT4_EOFBLOCKS_FL) 102 ext4_truncate(inode); 103 104 handle = ext4_journal_start(inode, 1); 105 if (IS_ERR(handle)) { 106 err = PTR_ERR(handle); 107 goto flags_out; 108 } 109 if (IS_SYNC(inode)) 110 ext4_handle_sync(handle); 111 err = ext4_reserve_inode_write(handle, inode, &iloc); 112 if (err) 113 goto flags_err; 114 115 flags = flags & EXT4_FL_USER_MODIFIABLE; 116 flags |= oldflags & ~EXT4_FL_USER_MODIFIABLE; 117 ei->i_flags = flags; 118 119 ext4_set_inode_flags(inode); 120 inode->i_ctime = ext4_current_time(inode); 121 122 err = ext4_mark_iloc_dirty(handle, inode, &iloc); 123 flags_err: 124 ext4_journal_stop(handle); 125 if (err) 126 goto flags_out; 127 128 if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) 129 err = ext4_change_inode_journal_flag(inode, jflag); 130 if (err) 131 goto flags_out; 132 if (migrate) 133 err = ext4_ext_migrate(inode); 134 flags_out: 135 mutex_unlock(&inode->i_mutex); 136 mnt_drop_write(filp->f_path.mnt); 137 return err; 138 } 139 case EXT4_IOC_GETVERSION: 140 case EXT4_IOC_GETVERSION_OLD: 141 return put_user(inode->i_generation, (int __user *) arg); 142 case EXT4_IOC_SETVERSION: 143 case EXT4_IOC_SETVERSION_OLD: { 144 handle_t *handle; 145 struct ext4_iloc iloc; 146 __u32 generation; 147 int err; 148 149 if (!inode_owner_or_capable(inode)) 150 return -EPERM; 151 152 err = mnt_want_write(filp->f_path.mnt); 153 if (err) 154 return err; 155 if (get_user(generation, (int __user *) arg)) { 156 err = -EFAULT; 157 goto setversion_out; 158 } 159 160 handle = ext4_journal_start(inode, 1); 161 if (IS_ERR(handle)) { 162 err = PTR_ERR(handle); 163 goto setversion_out; 164 } 165 err = ext4_reserve_inode_write(handle, inode, &iloc); 166 if (err == 0) { 167 inode->i_ctime = ext4_current_time(inode); 168 inode->i_generation = generation; 169 err = ext4_mark_iloc_dirty(handle, inode, &iloc); 170 } 171 ext4_journal_stop(handle); 172 setversion_out: 173 mnt_drop_write(filp->f_path.mnt); 174 return err; 175 } 176 #ifdef CONFIG_JBD2_DEBUG 177 case EXT4_IOC_WAIT_FOR_READONLY: 178 /* 179 * This is racy - by the time we're woken up and running, 180 * the superblock could be released. And the module could 181 * have been unloaded. So sue me. 182 * 183 * Returns 1 if it slept, else zero. 184 */ 185 { 186 struct super_block *sb = inode->i_sb; 187 DECLARE_WAITQUEUE(wait, current); 188 int ret = 0; 189 190 set_current_state(TASK_INTERRUPTIBLE); 191 add_wait_queue(&EXT4_SB(sb)->ro_wait_queue, &wait); 192 if (timer_pending(&EXT4_SB(sb)->turn_ro_timer)) { 193 schedule(); 194 ret = 1; 195 } 196 remove_wait_queue(&EXT4_SB(sb)->ro_wait_queue, &wait); 197 return ret; 198 } 199 #endif 200 case EXT4_IOC_GROUP_EXTEND: { 201 ext4_fsblk_t n_blocks_count; 202 struct super_block *sb = inode->i_sb; 203 int err, err2=0; 204 205 err = ext4_resize_begin(sb); 206 if (err) 207 return err; 208 209 if (get_user(n_blocks_count, (__u32 __user *)arg)) 210 return -EFAULT; 211 212 err = mnt_want_write(filp->f_path.mnt); 213 if (err) 214 return err; 215 216 err = ext4_group_extend(sb, EXT4_SB(sb)->s_es, n_blocks_count); 217 if (EXT4_SB(sb)->s_journal) { 218 jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); 219 err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal); 220 jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); 221 } 222 if (err == 0) 223 err = err2; 224 mnt_drop_write(filp->f_path.mnt); 225 ext4_resize_end(sb); 226 227 return err; 228 } 229 230 case EXT4_IOC_MOVE_EXT: { 231 struct move_extent me; 232 struct file *donor_filp; 233 int err; 234 235 if (!(filp->f_mode & FMODE_READ) || 236 !(filp->f_mode & FMODE_WRITE)) 237 return -EBADF; 238 239 if (copy_from_user(&me, 240 (struct move_extent __user *)arg, sizeof(me))) 241 return -EFAULT; 242 me.moved_len = 0; 243 244 donor_filp = fget(me.donor_fd); 245 if (!donor_filp) 246 return -EBADF; 247 248 if (!(donor_filp->f_mode & FMODE_WRITE)) { 249 err = -EBADF; 250 goto mext_out; 251 } 252 253 err = mnt_want_write(filp->f_path.mnt); 254 if (err) 255 goto mext_out; 256 257 err = ext4_move_extents(filp, donor_filp, me.orig_start, 258 me.donor_start, me.len, &me.moved_len); 259 mnt_drop_write(filp->f_path.mnt); 260 if (me.moved_len > 0) 261 file_remove_suid(donor_filp); 262 263 if (copy_to_user((struct move_extent __user *)arg, 264 &me, sizeof(me))) 265 err = -EFAULT; 266 mext_out: 267 fput(donor_filp); 268 return err; 269 } 270 271 case EXT4_IOC_GROUP_ADD: { 272 struct ext4_new_group_data input; 273 struct super_block *sb = inode->i_sb; 274 int err, err2=0; 275 276 err = ext4_resize_begin(sb); 277 if (err) 278 return err; 279 280 if (copy_from_user(&input, (struct ext4_new_group_input __user *)arg, 281 sizeof(input))) 282 return -EFAULT; 283 284 err = mnt_want_write(filp->f_path.mnt); 285 if (err) 286 return err; 287 288 err = ext4_group_add(sb, &input); 289 if (EXT4_SB(sb)->s_journal) { 290 jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); 291 err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal); 292 jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); 293 } 294 if (err == 0) 295 err = err2; 296 mnt_drop_write(filp->f_path.mnt); 297 ext4_resize_end(sb); 298 299 return err; 300 } 301 302 case EXT4_IOC_MIGRATE: 303 { 304 int err; 305 if (!inode_owner_or_capable(inode)) 306 return -EACCES; 307 308 err = mnt_want_write(filp->f_path.mnt); 309 if (err) 310 return err; 311 /* 312 * inode_mutex prevent write and truncate on the file. 313 * Read still goes through. We take i_data_sem in 314 * ext4_ext_swap_inode_data before we switch the 315 * inode format to prevent read. 316 */ 317 mutex_lock(&(inode->i_mutex)); 318 err = ext4_ext_migrate(inode); 319 mutex_unlock(&(inode->i_mutex)); 320 mnt_drop_write(filp->f_path.mnt); 321 return err; 322 } 323 324 case EXT4_IOC_ALLOC_DA_BLKS: 325 { 326 int err; 327 if (!inode_owner_or_capable(inode)) 328 return -EACCES; 329 330 err = mnt_want_write(filp->f_path.mnt); 331 if (err) 332 return err; 333 err = ext4_alloc_da_blocks(inode); 334 mnt_drop_write(filp->f_path.mnt); 335 return err; 336 } 337 338 case FITRIM: 339 { 340 struct super_block *sb = inode->i_sb; 341 struct request_queue *q = bdev_get_queue(sb->s_bdev); 342 struct fstrim_range range; 343 int ret = 0; 344 345 if (!capable(CAP_SYS_ADMIN)) 346 return -EPERM; 347 348 if (!blk_queue_discard(q)) 349 return -EOPNOTSUPP; 350 351 if (copy_from_user(&range, (struct fstrim_range *)arg, 352 sizeof(range))) 353 return -EFAULT; 354 355 range.minlen = max((unsigned int)range.minlen, 356 q->limits.discard_granularity); 357 ret = ext4_trim_fs(sb, &range); 358 if (ret < 0) 359 return ret; 360 361 if (copy_to_user((struct fstrim_range *)arg, &range, 362 sizeof(range))) 363 return -EFAULT; 364 365 return 0; 366 } 367 368 default: 369 return -ENOTTY; 370 } 371 } 372 373 #ifdef CONFIG_COMPAT 374 long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 375 { 376 /* These are just misnamed, they actually get/put from/to user an int */ 377 switch (cmd) { 378 case EXT4_IOC32_GETFLAGS: 379 cmd = EXT4_IOC_GETFLAGS; 380 break; 381 case EXT4_IOC32_SETFLAGS: 382 cmd = EXT4_IOC_SETFLAGS; 383 break; 384 case EXT4_IOC32_GETVERSION: 385 cmd = EXT4_IOC_GETVERSION; 386 break; 387 case EXT4_IOC32_SETVERSION: 388 cmd = EXT4_IOC_SETVERSION; 389 break; 390 case EXT4_IOC32_GROUP_EXTEND: 391 cmd = EXT4_IOC_GROUP_EXTEND; 392 break; 393 case EXT4_IOC32_GETVERSION_OLD: 394 cmd = EXT4_IOC_GETVERSION_OLD; 395 break; 396 case EXT4_IOC32_SETVERSION_OLD: 397 cmd = EXT4_IOC_SETVERSION_OLD; 398 break; 399 #ifdef CONFIG_JBD2_DEBUG 400 case EXT4_IOC32_WAIT_FOR_READONLY: 401 cmd = EXT4_IOC_WAIT_FOR_READONLY; 402 break; 403 #endif 404 case EXT4_IOC32_GETRSVSZ: 405 cmd = EXT4_IOC_GETRSVSZ; 406 break; 407 case EXT4_IOC32_SETRSVSZ: 408 cmd = EXT4_IOC_SETRSVSZ; 409 break; 410 case EXT4_IOC32_GROUP_ADD: { 411 struct compat_ext4_new_group_input __user *uinput; 412 struct ext4_new_group_input input; 413 mm_segment_t old_fs; 414 int err; 415 416 uinput = compat_ptr(arg); 417 err = get_user(input.group, &uinput->group); 418 err |= get_user(input.block_bitmap, &uinput->block_bitmap); 419 err |= get_user(input.inode_bitmap, &uinput->inode_bitmap); 420 err |= get_user(input.inode_table, &uinput->inode_table); 421 err |= get_user(input.blocks_count, &uinput->blocks_count); 422 err |= get_user(input.reserved_blocks, 423 &uinput->reserved_blocks); 424 if (err) 425 return -EFAULT; 426 old_fs = get_fs(); 427 set_fs(KERNEL_DS); 428 err = ext4_ioctl(file, EXT4_IOC_GROUP_ADD, 429 (unsigned long) &input); 430 set_fs(old_fs); 431 return err; 432 } 433 case EXT4_IOC_MOVE_EXT: 434 case FITRIM: 435 break; 436 default: 437 return -ENOIOCTLCMD; 438 } 439 return ext4_ioctl(file, cmd, (unsigned long) compat_ptr(arg)); 440 } 441 #endif 442