1 /* 2 * ioctl.c - NILFS ioctl operations. 3 * 4 * Copyright (C) 2007, 2008 Nippon Telegraph and Telephone Corporation. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 * 20 * Written by Koji Sato <koji@osrg.net>. 21 */ 22 23 #include <linux/fs.h> 24 #include <linux/wait.h> 25 #include <linux/slab.h> 26 #include <linux/capability.h> /* capable() */ 27 #include <linux/uaccess.h> /* copy_from_user(), copy_to_user() */ 28 #include <linux/vmalloc.h> 29 #include <linux/compat.h> /* compat_ptr() */ 30 #include <linux/mount.h> /* mnt_want_write(), mnt_drop_write() */ 31 #include <linux/buffer_head.h> 32 #include <linux/nilfs2_fs.h> 33 #include "nilfs.h" 34 #include "segment.h" 35 #include "bmap.h" 36 #include "cpfile.h" 37 #include "sufile.h" 38 #include "dat.h" 39 40 41 static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs, 42 struct nilfs_argv *argv, int dir, 43 ssize_t (*dofunc)(struct the_nilfs *, 44 __u64 *, int, 45 void *, size_t, size_t)) 46 { 47 void *buf; 48 void __user *base = (void __user *)(unsigned long)argv->v_base; 49 size_t maxmembs, total, n; 50 ssize_t nr; 51 int ret, i; 52 __u64 pos, ppos; 53 54 if (argv->v_nmembs == 0) 55 return 0; 56 57 if (argv->v_size > PAGE_SIZE) 58 return -EINVAL; 59 60 buf = (void *)__get_free_pages(GFP_NOFS, 0); 61 if (unlikely(!buf)) 62 return -ENOMEM; 63 maxmembs = PAGE_SIZE / argv->v_size; 64 65 ret = 0; 66 total = 0; 67 pos = argv->v_index; 68 for (i = 0; i < argv->v_nmembs; i += n) { 69 n = (argv->v_nmembs - i < maxmembs) ? 70 argv->v_nmembs - i : maxmembs; 71 if ((dir & _IOC_WRITE) && 72 copy_from_user(buf, base + argv->v_size * i, 73 argv->v_size * n)) { 74 ret = -EFAULT; 75 break; 76 } 77 ppos = pos; 78 nr = dofunc(nilfs, &pos, argv->v_flags, buf, argv->v_size, 79 n); 80 if (nr < 0) { 81 ret = nr; 82 break; 83 } 84 if ((dir & _IOC_READ) && 85 copy_to_user(base + argv->v_size * i, buf, 86 argv->v_size * nr)) { 87 ret = -EFAULT; 88 break; 89 } 90 total += nr; 91 if ((size_t)nr < n) 92 break; 93 if (pos == ppos) 94 pos += n; 95 } 96 argv->v_nmembs = total; 97 98 free_pages((unsigned long)buf, 0); 99 return ret; 100 } 101 102 static int nilfs_ioctl_getflags(struct inode *inode, void __user *argp) 103 { 104 unsigned int flags = NILFS_I(inode)->i_flags & FS_FL_USER_VISIBLE; 105 106 return put_user(flags, (int __user *)argp); 107 } 108 109 static int nilfs_ioctl_setflags(struct inode *inode, struct file *filp, 110 void __user *argp) 111 { 112 struct nilfs_transaction_info ti; 113 unsigned int flags, oldflags; 114 int ret; 115 116 if (!inode_owner_or_capable(inode)) 117 return -EACCES; 118 119 if (get_user(flags, (int __user *)argp)) 120 return -EFAULT; 121 122 ret = mnt_want_write(filp->f_path.mnt); 123 if (ret) 124 return ret; 125 126 flags = nilfs_mask_flags(inode->i_mode, flags); 127 128 mutex_lock(&inode->i_mutex); 129 130 oldflags = NILFS_I(inode)->i_flags; 131 132 /* 133 * The IMMUTABLE and APPEND_ONLY flags can only be changed by the 134 * relevant capability. 135 */ 136 ret = -EPERM; 137 if (((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) && 138 !capable(CAP_LINUX_IMMUTABLE)) 139 goto out; 140 141 ret = nilfs_transaction_begin(inode->i_sb, &ti, 0); 142 if (ret) 143 goto out; 144 145 NILFS_I(inode)->i_flags = (oldflags & ~FS_FL_USER_MODIFIABLE) | 146 (flags & FS_FL_USER_MODIFIABLE); 147 148 nilfs_set_inode_flags(inode); 149 inode->i_ctime = CURRENT_TIME; 150 if (IS_SYNC(inode)) 151 nilfs_set_transaction_flag(NILFS_TI_SYNC); 152 153 nilfs_mark_inode_dirty(inode); 154 ret = nilfs_transaction_commit(inode->i_sb); 155 out: 156 mutex_unlock(&inode->i_mutex); 157 mnt_drop_write(filp->f_path.mnt); 158 return ret; 159 } 160 161 static int nilfs_ioctl_getversion(struct inode *inode, void __user *argp) 162 { 163 return put_user(inode->i_generation, (int __user *)argp); 164 } 165 166 static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp, 167 unsigned int cmd, void __user *argp) 168 { 169 struct the_nilfs *nilfs = inode->i_sb->s_fs_info; 170 struct nilfs_transaction_info ti; 171 struct nilfs_cpmode cpmode; 172 int ret; 173 174 if (!capable(CAP_SYS_ADMIN)) 175 return -EPERM; 176 177 ret = mnt_want_write(filp->f_path.mnt); 178 if (ret) 179 return ret; 180 181 ret = -EFAULT; 182 if (copy_from_user(&cpmode, argp, sizeof(cpmode))) 183 goto out; 184 185 down_read(&inode->i_sb->s_umount); 186 187 nilfs_transaction_begin(inode->i_sb, &ti, 0); 188 ret = nilfs_cpfile_change_cpmode( 189 nilfs->ns_cpfile, cpmode.cm_cno, cpmode.cm_mode); 190 if (unlikely(ret < 0)) 191 nilfs_transaction_abort(inode->i_sb); 192 else 193 nilfs_transaction_commit(inode->i_sb); /* never fails */ 194 195 up_read(&inode->i_sb->s_umount); 196 out: 197 mnt_drop_write(filp->f_path.mnt); 198 return ret; 199 } 200 201 static int 202 nilfs_ioctl_delete_checkpoint(struct inode *inode, struct file *filp, 203 unsigned int cmd, void __user *argp) 204 { 205 struct the_nilfs *nilfs = inode->i_sb->s_fs_info; 206 struct nilfs_transaction_info ti; 207 __u64 cno; 208 int ret; 209 210 if (!capable(CAP_SYS_ADMIN)) 211 return -EPERM; 212 213 ret = mnt_want_write(filp->f_path.mnt); 214 if (ret) 215 return ret; 216 217 ret = -EFAULT; 218 if (copy_from_user(&cno, argp, sizeof(cno))) 219 goto out; 220 221 nilfs_transaction_begin(inode->i_sb, &ti, 0); 222 ret = nilfs_cpfile_delete_checkpoint(nilfs->ns_cpfile, cno); 223 if (unlikely(ret < 0)) 224 nilfs_transaction_abort(inode->i_sb); 225 else 226 nilfs_transaction_commit(inode->i_sb); /* never fails */ 227 out: 228 mnt_drop_write(filp->f_path.mnt); 229 return ret; 230 } 231 232 static ssize_t 233 nilfs_ioctl_do_get_cpinfo(struct the_nilfs *nilfs, __u64 *posp, int flags, 234 void *buf, size_t size, size_t nmembs) 235 { 236 int ret; 237 238 down_read(&nilfs->ns_segctor_sem); 239 ret = nilfs_cpfile_get_cpinfo(nilfs->ns_cpfile, posp, flags, buf, 240 size, nmembs); 241 up_read(&nilfs->ns_segctor_sem); 242 return ret; 243 } 244 245 static int nilfs_ioctl_get_cpstat(struct inode *inode, struct file *filp, 246 unsigned int cmd, void __user *argp) 247 { 248 struct the_nilfs *nilfs = inode->i_sb->s_fs_info; 249 struct nilfs_cpstat cpstat; 250 int ret; 251 252 down_read(&nilfs->ns_segctor_sem); 253 ret = nilfs_cpfile_get_stat(nilfs->ns_cpfile, &cpstat); 254 up_read(&nilfs->ns_segctor_sem); 255 if (ret < 0) 256 return ret; 257 258 if (copy_to_user(argp, &cpstat, sizeof(cpstat))) 259 ret = -EFAULT; 260 return ret; 261 } 262 263 static ssize_t 264 nilfs_ioctl_do_get_suinfo(struct the_nilfs *nilfs, __u64 *posp, int flags, 265 void *buf, size_t size, size_t nmembs) 266 { 267 int ret; 268 269 down_read(&nilfs->ns_segctor_sem); 270 ret = nilfs_sufile_get_suinfo(nilfs->ns_sufile, *posp, buf, size, 271 nmembs); 272 up_read(&nilfs->ns_segctor_sem); 273 return ret; 274 } 275 276 static int nilfs_ioctl_get_sustat(struct inode *inode, struct file *filp, 277 unsigned int cmd, void __user *argp) 278 { 279 struct the_nilfs *nilfs = inode->i_sb->s_fs_info; 280 struct nilfs_sustat sustat; 281 int ret; 282 283 down_read(&nilfs->ns_segctor_sem); 284 ret = nilfs_sufile_get_stat(nilfs->ns_sufile, &sustat); 285 up_read(&nilfs->ns_segctor_sem); 286 if (ret < 0) 287 return ret; 288 289 if (copy_to_user(argp, &sustat, sizeof(sustat))) 290 ret = -EFAULT; 291 return ret; 292 } 293 294 static ssize_t 295 nilfs_ioctl_do_get_vinfo(struct the_nilfs *nilfs, __u64 *posp, int flags, 296 void *buf, size_t size, size_t nmembs) 297 { 298 int ret; 299 300 down_read(&nilfs->ns_segctor_sem); 301 ret = nilfs_dat_get_vinfo(nilfs->ns_dat, buf, size, nmembs); 302 up_read(&nilfs->ns_segctor_sem); 303 return ret; 304 } 305 306 static ssize_t 307 nilfs_ioctl_do_get_bdescs(struct the_nilfs *nilfs, __u64 *posp, int flags, 308 void *buf, size_t size, size_t nmembs) 309 { 310 struct nilfs_bmap *bmap = NILFS_I(nilfs->ns_dat)->i_bmap; 311 struct nilfs_bdesc *bdescs = buf; 312 int ret, i; 313 314 down_read(&nilfs->ns_segctor_sem); 315 for (i = 0; i < nmembs; i++) { 316 ret = nilfs_bmap_lookup_at_level(bmap, 317 bdescs[i].bd_offset, 318 bdescs[i].bd_level + 1, 319 &bdescs[i].bd_blocknr); 320 if (ret < 0) { 321 if (ret != -ENOENT) { 322 up_read(&nilfs->ns_segctor_sem); 323 return ret; 324 } 325 bdescs[i].bd_blocknr = 0; 326 } 327 } 328 up_read(&nilfs->ns_segctor_sem); 329 return nmembs; 330 } 331 332 static int nilfs_ioctl_get_bdescs(struct inode *inode, struct file *filp, 333 unsigned int cmd, void __user *argp) 334 { 335 struct the_nilfs *nilfs = inode->i_sb->s_fs_info; 336 struct nilfs_argv argv; 337 int ret; 338 339 if (copy_from_user(&argv, argp, sizeof(argv))) 340 return -EFAULT; 341 342 if (argv.v_size != sizeof(struct nilfs_bdesc)) 343 return -EINVAL; 344 345 ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd), 346 nilfs_ioctl_do_get_bdescs); 347 if (ret < 0) 348 return ret; 349 350 if (copy_to_user(argp, &argv, sizeof(argv))) 351 ret = -EFAULT; 352 return ret; 353 } 354 355 static int nilfs_ioctl_move_inode_block(struct inode *inode, 356 struct nilfs_vdesc *vdesc, 357 struct list_head *buffers) 358 { 359 struct buffer_head *bh; 360 int ret; 361 362 if (vdesc->vd_flags == 0) 363 ret = nilfs_gccache_submit_read_data( 364 inode, vdesc->vd_offset, vdesc->vd_blocknr, 365 vdesc->vd_vblocknr, &bh); 366 else 367 ret = nilfs_gccache_submit_read_node( 368 inode, vdesc->vd_blocknr, vdesc->vd_vblocknr, &bh); 369 370 if (unlikely(ret < 0)) { 371 if (ret == -ENOENT) 372 printk(KERN_CRIT 373 "%s: invalid virtual block address (%s): " 374 "ino=%llu, cno=%llu, offset=%llu, " 375 "blocknr=%llu, vblocknr=%llu\n", 376 __func__, vdesc->vd_flags ? "node" : "data", 377 (unsigned long long)vdesc->vd_ino, 378 (unsigned long long)vdesc->vd_cno, 379 (unsigned long long)vdesc->vd_offset, 380 (unsigned long long)vdesc->vd_blocknr, 381 (unsigned long long)vdesc->vd_vblocknr); 382 return ret; 383 } 384 if (unlikely(!list_empty(&bh->b_assoc_buffers))) { 385 printk(KERN_CRIT "%s: conflicting %s buffer: ino=%llu, " 386 "cno=%llu, offset=%llu, blocknr=%llu, vblocknr=%llu\n", 387 __func__, vdesc->vd_flags ? "node" : "data", 388 (unsigned long long)vdesc->vd_ino, 389 (unsigned long long)vdesc->vd_cno, 390 (unsigned long long)vdesc->vd_offset, 391 (unsigned long long)vdesc->vd_blocknr, 392 (unsigned long long)vdesc->vd_vblocknr); 393 brelse(bh); 394 return -EEXIST; 395 } 396 list_add_tail(&bh->b_assoc_buffers, buffers); 397 return 0; 398 } 399 400 static int nilfs_ioctl_move_blocks(struct super_block *sb, 401 struct nilfs_argv *argv, void *buf) 402 { 403 size_t nmembs = argv->v_nmembs; 404 struct the_nilfs *nilfs = sb->s_fs_info; 405 struct inode *inode; 406 struct nilfs_vdesc *vdesc; 407 struct buffer_head *bh, *n; 408 LIST_HEAD(buffers); 409 ino_t ino; 410 __u64 cno; 411 int i, ret; 412 413 for (i = 0, vdesc = buf; i < nmembs; ) { 414 ino = vdesc->vd_ino; 415 cno = vdesc->vd_cno; 416 inode = nilfs_iget_for_gc(sb, ino, cno); 417 if (IS_ERR(inode)) { 418 ret = PTR_ERR(inode); 419 goto failed; 420 } 421 if (list_empty(&NILFS_I(inode)->i_dirty)) { 422 /* 423 * Add the inode to GC inode list. Garbage Collection 424 * is serialized and no two processes manipulate the 425 * list simultaneously. 426 */ 427 igrab(inode); 428 list_add(&NILFS_I(inode)->i_dirty, 429 &nilfs->ns_gc_inodes); 430 } 431 432 do { 433 ret = nilfs_ioctl_move_inode_block(inode, vdesc, 434 &buffers); 435 if (unlikely(ret < 0)) { 436 iput(inode); 437 goto failed; 438 } 439 vdesc++; 440 } while (++i < nmembs && 441 vdesc->vd_ino == ino && vdesc->vd_cno == cno); 442 443 iput(inode); /* The inode still remains in GC inode list */ 444 } 445 446 list_for_each_entry_safe(bh, n, &buffers, b_assoc_buffers) { 447 ret = nilfs_gccache_wait_and_mark_dirty(bh); 448 if (unlikely(ret < 0)) { 449 WARN_ON(ret == -EEXIST); 450 goto failed; 451 } 452 list_del_init(&bh->b_assoc_buffers); 453 brelse(bh); 454 } 455 return nmembs; 456 457 failed: 458 list_for_each_entry_safe(bh, n, &buffers, b_assoc_buffers) { 459 list_del_init(&bh->b_assoc_buffers); 460 brelse(bh); 461 } 462 return ret; 463 } 464 465 static int nilfs_ioctl_delete_checkpoints(struct the_nilfs *nilfs, 466 struct nilfs_argv *argv, void *buf) 467 { 468 size_t nmembs = argv->v_nmembs; 469 struct inode *cpfile = nilfs->ns_cpfile; 470 struct nilfs_period *periods = buf; 471 int ret, i; 472 473 for (i = 0; i < nmembs; i++) { 474 ret = nilfs_cpfile_delete_checkpoints( 475 cpfile, periods[i].p_start, periods[i].p_end); 476 if (ret < 0) 477 return ret; 478 } 479 return nmembs; 480 } 481 482 static int nilfs_ioctl_free_vblocknrs(struct the_nilfs *nilfs, 483 struct nilfs_argv *argv, void *buf) 484 { 485 size_t nmembs = argv->v_nmembs; 486 int ret; 487 488 ret = nilfs_dat_freev(nilfs->ns_dat, buf, nmembs); 489 490 return (ret < 0) ? ret : nmembs; 491 } 492 493 static int nilfs_ioctl_mark_blocks_dirty(struct the_nilfs *nilfs, 494 struct nilfs_argv *argv, void *buf) 495 { 496 size_t nmembs = argv->v_nmembs; 497 struct nilfs_bmap *bmap = NILFS_I(nilfs->ns_dat)->i_bmap; 498 struct nilfs_bdesc *bdescs = buf; 499 int ret, i; 500 501 for (i = 0; i < nmembs; i++) { 502 /* XXX: use macro or inline func to check liveness */ 503 ret = nilfs_bmap_lookup_at_level(bmap, 504 bdescs[i].bd_offset, 505 bdescs[i].bd_level + 1, 506 &bdescs[i].bd_blocknr); 507 if (ret < 0) { 508 if (ret != -ENOENT) 509 return ret; 510 bdescs[i].bd_blocknr = 0; 511 } 512 if (bdescs[i].bd_blocknr != bdescs[i].bd_oblocknr) 513 /* skip dead block */ 514 continue; 515 if (bdescs[i].bd_level == 0) { 516 ret = nilfs_mdt_mark_block_dirty(nilfs->ns_dat, 517 bdescs[i].bd_offset); 518 if (ret < 0) { 519 WARN_ON(ret == -ENOENT); 520 return ret; 521 } 522 } else { 523 ret = nilfs_bmap_mark(bmap, bdescs[i].bd_offset, 524 bdescs[i].bd_level); 525 if (ret < 0) { 526 WARN_ON(ret == -ENOENT); 527 return ret; 528 } 529 } 530 } 531 return nmembs; 532 } 533 534 int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *nilfs, 535 struct nilfs_argv *argv, void **kbufs) 536 { 537 const char *msg; 538 int ret; 539 540 ret = nilfs_ioctl_delete_checkpoints(nilfs, &argv[1], kbufs[1]); 541 if (ret < 0) { 542 /* 543 * can safely abort because checkpoints can be removed 544 * independently. 545 */ 546 msg = "cannot delete checkpoints"; 547 goto failed; 548 } 549 ret = nilfs_ioctl_free_vblocknrs(nilfs, &argv[2], kbufs[2]); 550 if (ret < 0) { 551 /* 552 * can safely abort because DAT file is updated atomically 553 * using a copy-on-write technique. 554 */ 555 msg = "cannot delete virtual blocks from DAT file"; 556 goto failed; 557 } 558 ret = nilfs_ioctl_mark_blocks_dirty(nilfs, &argv[3], kbufs[3]); 559 if (ret < 0) { 560 /* 561 * can safely abort because the operation is nondestructive. 562 */ 563 msg = "cannot mark copying blocks dirty"; 564 goto failed; 565 } 566 return 0; 567 568 failed: 569 printk(KERN_ERR "NILFS: GC failed during preparation: %s: err=%d\n", 570 msg, ret); 571 return ret; 572 } 573 574 static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp, 575 unsigned int cmd, void __user *argp) 576 { 577 struct nilfs_argv argv[5]; 578 static const size_t argsz[5] = { 579 sizeof(struct nilfs_vdesc), 580 sizeof(struct nilfs_period), 581 sizeof(__u64), 582 sizeof(struct nilfs_bdesc), 583 sizeof(__u64), 584 }; 585 void __user *base; 586 void *kbufs[5]; 587 struct the_nilfs *nilfs; 588 size_t len, nsegs; 589 int n, ret; 590 591 if (!capable(CAP_SYS_ADMIN)) 592 return -EPERM; 593 594 ret = mnt_want_write(filp->f_path.mnt); 595 if (ret) 596 return ret; 597 598 ret = -EFAULT; 599 if (copy_from_user(argv, argp, sizeof(argv))) 600 goto out; 601 602 ret = -EINVAL; 603 nsegs = argv[4].v_nmembs; 604 if (argv[4].v_size != argsz[4]) 605 goto out; 606 607 /* 608 * argv[4] points to segment numbers this ioctl cleans. We 609 * use kmalloc() for its buffer because memory used for the 610 * segment numbers is enough small. 611 */ 612 kbufs[4] = memdup_user((void __user *)(unsigned long)argv[4].v_base, 613 nsegs * sizeof(__u64)); 614 if (IS_ERR(kbufs[4])) { 615 ret = PTR_ERR(kbufs[4]); 616 goto out; 617 } 618 nilfs = inode->i_sb->s_fs_info; 619 620 for (n = 0; n < 4; n++) { 621 ret = -EINVAL; 622 if (argv[n].v_size != argsz[n]) 623 goto out_free; 624 625 if (argv[n].v_nmembs > nsegs * nilfs->ns_blocks_per_segment) 626 goto out_free; 627 628 len = argv[n].v_size * argv[n].v_nmembs; 629 base = (void __user *)(unsigned long)argv[n].v_base; 630 if (len == 0) { 631 kbufs[n] = NULL; 632 continue; 633 } 634 635 kbufs[n] = vmalloc(len); 636 if (!kbufs[n]) { 637 ret = -ENOMEM; 638 goto out_free; 639 } 640 if (copy_from_user(kbufs[n], base, len)) { 641 ret = -EFAULT; 642 vfree(kbufs[n]); 643 goto out_free; 644 } 645 } 646 647 /* 648 * nilfs_ioctl_move_blocks() will call nilfs_iget_for_gc(), 649 * which will operates an inode list without blocking. 650 * To protect the list from concurrent operations, 651 * nilfs_ioctl_move_blocks should be atomic operation. 652 */ 653 if (test_and_set_bit(THE_NILFS_GC_RUNNING, &nilfs->ns_flags)) { 654 ret = -EBUSY; 655 goto out_free; 656 } 657 658 vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); 659 660 ret = nilfs_ioctl_move_blocks(inode->i_sb, &argv[0], kbufs[0]); 661 if (ret < 0) 662 printk(KERN_ERR "NILFS: GC failed during preparation: " 663 "cannot read source blocks: err=%d\n", ret); 664 else 665 ret = nilfs_clean_segments(inode->i_sb, argv, kbufs); 666 667 nilfs_remove_all_gcinodes(nilfs); 668 clear_nilfs_gc_running(nilfs); 669 670 out_free: 671 while (--n >= 0) 672 vfree(kbufs[n]); 673 kfree(kbufs[4]); 674 out: 675 mnt_drop_write(filp->f_path.mnt); 676 return ret; 677 } 678 679 static int nilfs_ioctl_sync(struct inode *inode, struct file *filp, 680 unsigned int cmd, void __user *argp) 681 { 682 __u64 cno; 683 int ret; 684 struct the_nilfs *nilfs; 685 686 ret = nilfs_construct_segment(inode->i_sb); 687 if (ret < 0) 688 return ret; 689 690 if (argp != NULL) { 691 nilfs = inode->i_sb->s_fs_info; 692 down_read(&nilfs->ns_segctor_sem); 693 cno = nilfs->ns_cno - 1; 694 up_read(&nilfs->ns_segctor_sem); 695 if (copy_to_user(argp, &cno, sizeof(cno))) 696 return -EFAULT; 697 } 698 return 0; 699 } 700 701 static int nilfs_ioctl_resize(struct inode *inode, struct file *filp, 702 void __user *argp) 703 { 704 __u64 newsize; 705 int ret = -EPERM; 706 707 if (!capable(CAP_SYS_ADMIN)) 708 goto out; 709 710 ret = mnt_want_write(filp->f_path.mnt); 711 if (ret) 712 goto out; 713 714 ret = -EFAULT; 715 if (copy_from_user(&newsize, argp, sizeof(newsize))) 716 goto out_drop_write; 717 718 ret = nilfs_resize_fs(inode->i_sb, newsize); 719 720 out_drop_write: 721 mnt_drop_write(filp->f_path.mnt); 722 out: 723 return ret; 724 } 725 726 static int nilfs_ioctl_set_alloc_range(struct inode *inode, void __user *argp) 727 { 728 struct the_nilfs *nilfs = inode->i_sb->s_fs_info; 729 __u64 range[2]; 730 __u64 minseg, maxseg; 731 unsigned long segbytes; 732 int ret = -EPERM; 733 734 if (!capable(CAP_SYS_ADMIN)) 735 goto out; 736 737 ret = -EFAULT; 738 if (copy_from_user(range, argp, sizeof(__u64[2]))) 739 goto out; 740 741 ret = -ERANGE; 742 if (range[1] > i_size_read(inode->i_sb->s_bdev->bd_inode)) 743 goto out; 744 745 segbytes = nilfs->ns_blocks_per_segment * nilfs->ns_blocksize; 746 747 minseg = range[0] + segbytes - 1; 748 do_div(minseg, segbytes); 749 maxseg = NILFS_SB2_OFFSET_BYTES(range[1]); 750 do_div(maxseg, segbytes); 751 maxseg--; 752 753 ret = nilfs_sufile_set_alloc_range(nilfs->ns_sufile, minseg, maxseg); 754 out: 755 return ret; 756 } 757 758 static int nilfs_ioctl_get_info(struct inode *inode, struct file *filp, 759 unsigned int cmd, void __user *argp, 760 size_t membsz, 761 ssize_t (*dofunc)(struct the_nilfs *, 762 __u64 *, int, 763 void *, size_t, size_t)) 764 765 { 766 struct the_nilfs *nilfs = inode->i_sb->s_fs_info; 767 struct nilfs_argv argv; 768 int ret; 769 770 if (copy_from_user(&argv, argp, sizeof(argv))) 771 return -EFAULT; 772 773 if (argv.v_size < membsz) 774 return -EINVAL; 775 776 ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd), dofunc); 777 if (ret < 0) 778 return ret; 779 780 if (copy_to_user(argp, &argv, sizeof(argv))) 781 ret = -EFAULT; 782 return ret; 783 } 784 785 long nilfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 786 { 787 struct inode *inode = filp->f_dentry->d_inode; 788 void __user *argp = (void __user *)arg; 789 790 switch (cmd) { 791 case FS_IOC_GETFLAGS: 792 return nilfs_ioctl_getflags(inode, argp); 793 case FS_IOC_SETFLAGS: 794 return nilfs_ioctl_setflags(inode, filp, argp); 795 case FS_IOC_GETVERSION: 796 return nilfs_ioctl_getversion(inode, argp); 797 case NILFS_IOCTL_CHANGE_CPMODE: 798 return nilfs_ioctl_change_cpmode(inode, filp, cmd, argp); 799 case NILFS_IOCTL_DELETE_CHECKPOINT: 800 return nilfs_ioctl_delete_checkpoint(inode, filp, cmd, argp); 801 case NILFS_IOCTL_GET_CPINFO: 802 return nilfs_ioctl_get_info(inode, filp, cmd, argp, 803 sizeof(struct nilfs_cpinfo), 804 nilfs_ioctl_do_get_cpinfo); 805 case NILFS_IOCTL_GET_CPSTAT: 806 return nilfs_ioctl_get_cpstat(inode, filp, cmd, argp); 807 case NILFS_IOCTL_GET_SUINFO: 808 return nilfs_ioctl_get_info(inode, filp, cmd, argp, 809 sizeof(struct nilfs_suinfo), 810 nilfs_ioctl_do_get_suinfo); 811 case NILFS_IOCTL_GET_SUSTAT: 812 return nilfs_ioctl_get_sustat(inode, filp, cmd, argp); 813 case NILFS_IOCTL_GET_VINFO: 814 return nilfs_ioctl_get_info(inode, filp, cmd, argp, 815 sizeof(struct nilfs_vinfo), 816 nilfs_ioctl_do_get_vinfo); 817 case NILFS_IOCTL_GET_BDESCS: 818 return nilfs_ioctl_get_bdescs(inode, filp, cmd, argp); 819 case NILFS_IOCTL_CLEAN_SEGMENTS: 820 return nilfs_ioctl_clean_segments(inode, filp, cmd, argp); 821 case NILFS_IOCTL_SYNC: 822 return nilfs_ioctl_sync(inode, filp, cmd, argp); 823 case NILFS_IOCTL_RESIZE: 824 return nilfs_ioctl_resize(inode, filp, argp); 825 case NILFS_IOCTL_SET_ALLOC_RANGE: 826 return nilfs_ioctl_set_alloc_range(inode, argp); 827 default: 828 return -ENOTTY; 829 } 830 } 831 832 #ifdef CONFIG_COMPAT 833 long nilfs_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 834 { 835 switch (cmd) { 836 case FS_IOC32_GETFLAGS: 837 cmd = FS_IOC_GETFLAGS; 838 break; 839 case FS_IOC32_SETFLAGS: 840 cmd = FS_IOC_SETFLAGS; 841 break; 842 case FS_IOC32_GETVERSION: 843 cmd = FS_IOC_GETVERSION; 844 break; 845 default: 846 return -ENOIOCTLCMD; 847 } 848 return nilfs_ioctl(filp, cmd, (unsigned long)compat_ptr(arg)); 849 } 850 #endif 851