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