diff options
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r-- | fs/btrfs/ioctl.c | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index f580a3a5d2fc..205cd011d2f3 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -1803,6 +1803,75 @@ static long btrfs_ioctl_rm_dev(struct btrfs_root *root, void __user *arg) | |||
1803 | return ret; | 1803 | return ret; |
1804 | } | 1804 | } |
1805 | 1805 | ||
1806 | static long btrfs_ioctl_fs_info(struct btrfs_root *root, void __user *arg) | ||
1807 | { | ||
1808 | struct btrfs_ioctl_fs_info_args fi_args; | ||
1809 | struct btrfs_device *device; | ||
1810 | struct btrfs_device *next; | ||
1811 | struct btrfs_fs_devices *fs_devices = root->fs_info->fs_devices; | ||
1812 | |||
1813 | if (!capable(CAP_SYS_ADMIN)) | ||
1814 | return -EPERM; | ||
1815 | |||
1816 | fi_args.num_devices = fs_devices->num_devices; | ||
1817 | fi_args.max_id = 0; | ||
1818 | memcpy(&fi_args.fsid, root->fs_info->fsid, sizeof(fi_args.fsid)); | ||
1819 | |||
1820 | mutex_lock(&fs_devices->device_list_mutex); | ||
1821 | list_for_each_entry_safe(device, next, &fs_devices->devices, dev_list) { | ||
1822 | if (device->devid > fi_args.max_id) | ||
1823 | fi_args.max_id = device->devid; | ||
1824 | } | ||
1825 | mutex_unlock(&fs_devices->device_list_mutex); | ||
1826 | |||
1827 | if (copy_to_user(arg, &fi_args, sizeof(fi_args))) | ||
1828 | return -EFAULT; | ||
1829 | |||
1830 | return 0; | ||
1831 | } | ||
1832 | |||
1833 | static long btrfs_ioctl_dev_info(struct btrfs_root *root, void __user *arg) | ||
1834 | { | ||
1835 | struct btrfs_ioctl_dev_info_args *di_args; | ||
1836 | struct btrfs_device *dev; | ||
1837 | struct btrfs_fs_devices *fs_devices = root->fs_info->fs_devices; | ||
1838 | int ret = 0; | ||
1839 | char *s_uuid = NULL; | ||
1840 | char empty_uuid[BTRFS_UUID_SIZE] = {0}; | ||
1841 | |||
1842 | if (!capable(CAP_SYS_ADMIN)) | ||
1843 | return -EPERM; | ||
1844 | |||
1845 | di_args = memdup_user(arg, sizeof(*di_args)); | ||
1846 | if (IS_ERR(di_args)) | ||
1847 | return PTR_ERR(di_args); | ||
1848 | |||
1849 | if (memcmp(empty_uuid, di_args->uuid, BTRFS_UUID_SIZE) != 0) | ||
1850 | s_uuid = di_args->uuid; | ||
1851 | |||
1852 | mutex_lock(&fs_devices->device_list_mutex); | ||
1853 | dev = btrfs_find_device(root, di_args->devid, s_uuid, NULL); | ||
1854 | mutex_unlock(&fs_devices->device_list_mutex); | ||
1855 | |||
1856 | if (!dev) { | ||
1857 | ret = -ENODEV; | ||
1858 | goto out; | ||
1859 | } | ||
1860 | |||
1861 | di_args->devid = dev->devid; | ||
1862 | di_args->bytes_used = dev->bytes_used; | ||
1863 | di_args->total_bytes = dev->total_bytes; | ||
1864 | memcpy(di_args->uuid, dev->uuid, sizeof(di_args->uuid)); | ||
1865 | strncpy(di_args->path, dev->name, sizeof(di_args->path)); | ||
1866 | |||
1867 | out: | ||
1868 | if (ret == 0 && copy_to_user(arg, di_args, sizeof(*di_args))) | ||
1869 | ret = -EFAULT; | ||
1870 | |||
1871 | kfree(di_args); | ||
1872 | return ret; | ||
1873 | } | ||
1874 | |||
1806 | static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | 1875 | static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, |
1807 | u64 off, u64 olen, u64 destoff) | 1876 | u64 off, u64 olen, u64 destoff) |
1808 | { | 1877 | { |
@@ -2465,6 +2534,58 @@ static noinline long btrfs_ioctl_wait_sync(struct file *file, void __user *argp) | |||
2465 | return btrfs_wait_for_commit(root, transid); | 2534 | return btrfs_wait_for_commit(root, transid); |
2466 | } | 2535 | } |
2467 | 2536 | ||
2537 | static long btrfs_ioctl_scrub(struct btrfs_root *root, void __user *arg) | ||
2538 | { | ||
2539 | int ret; | ||
2540 | struct btrfs_ioctl_scrub_args *sa; | ||
2541 | |||
2542 | if (!capable(CAP_SYS_ADMIN)) | ||
2543 | return -EPERM; | ||
2544 | |||
2545 | sa = memdup_user(arg, sizeof(*sa)); | ||
2546 | if (IS_ERR(sa)) | ||
2547 | return PTR_ERR(sa); | ||
2548 | |||
2549 | ret = btrfs_scrub_dev(root, sa->devid, sa->start, sa->end, | ||
2550 | &sa->progress); | ||
2551 | |||
2552 | if (copy_to_user(arg, sa, sizeof(*sa))) | ||
2553 | ret = -EFAULT; | ||
2554 | |||
2555 | kfree(sa); | ||
2556 | return ret; | ||
2557 | } | ||
2558 | |||
2559 | static long btrfs_ioctl_scrub_cancel(struct btrfs_root *root, void __user *arg) | ||
2560 | { | ||
2561 | if (!capable(CAP_SYS_ADMIN)) | ||
2562 | return -EPERM; | ||
2563 | |||
2564 | return btrfs_scrub_cancel(root); | ||
2565 | } | ||
2566 | |||
2567 | static long btrfs_ioctl_scrub_progress(struct btrfs_root *root, | ||
2568 | void __user *arg) | ||
2569 | { | ||
2570 | struct btrfs_ioctl_scrub_args *sa; | ||
2571 | int ret; | ||
2572 | |||
2573 | if (!capable(CAP_SYS_ADMIN)) | ||
2574 | return -EPERM; | ||
2575 | |||
2576 | sa = memdup_user(arg, sizeof(*sa)); | ||
2577 | if (IS_ERR(sa)) | ||
2578 | return PTR_ERR(sa); | ||
2579 | |||
2580 | ret = btrfs_scrub_progress(root, sa->devid, &sa->progress); | ||
2581 | |||
2582 | if (copy_to_user(arg, sa, sizeof(*sa))) | ||
2583 | ret = -EFAULT; | ||
2584 | |||
2585 | kfree(sa); | ||
2586 | return ret; | ||
2587 | } | ||
2588 | |||
2468 | long btrfs_ioctl(struct file *file, unsigned int | 2589 | long btrfs_ioctl(struct file *file, unsigned int |
2469 | cmd, unsigned long arg) | 2590 | cmd, unsigned long arg) |
2470 | { | 2591 | { |
@@ -2504,6 +2625,10 @@ long btrfs_ioctl(struct file *file, unsigned int | |||
2504 | return btrfs_ioctl_add_dev(root, argp); | 2625 | return btrfs_ioctl_add_dev(root, argp); |
2505 | case BTRFS_IOC_RM_DEV: | 2626 | case BTRFS_IOC_RM_DEV: |
2506 | return btrfs_ioctl_rm_dev(root, argp); | 2627 | return btrfs_ioctl_rm_dev(root, argp); |
2628 | case BTRFS_IOC_FS_INFO: | ||
2629 | return btrfs_ioctl_fs_info(root, argp); | ||
2630 | case BTRFS_IOC_DEV_INFO: | ||
2631 | return btrfs_ioctl_dev_info(root, argp); | ||
2507 | case BTRFS_IOC_BALANCE: | 2632 | case BTRFS_IOC_BALANCE: |
2508 | return btrfs_balance(root->fs_info->dev_root); | 2633 | return btrfs_balance(root->fs_info->dev_root); |
2509 | case BTRFS_IOC_CLONE: | 2634 | case BTRFS_IOC_CLONE: |
@@ -2527,6 +2652,12 @@ long btrfs_ioctl(struct file *file, unsigned int | |||
2527 | return btrfs_ioctl_start_sync(file, argp); | 2652 | return btrfs_ioctl_start_sync(file, argp); |
2528 | case BTRFS_IOC_WAIT_SYNC: | 2653 | case BTRFS_IOC_WAIT_SYNC: |
2529 | return btrfs_ioctl_wait_sync(file, argp); | 2654 | return btrfs_ioctl_wait_sync(file, argp); |
2655 | case BTRFS_IOC_SCRUB: | ||
2656 | return btrfs_ioctl_scrub(root, argp); | ||
2657 | case BTRFS_IOC_SCRUB_CANCEL: | ||
2658 | return btrfs_ioctl_scrub_cancel(root, argp); | ||
2659 | case BTRFS_IOC_SCRUB_PROGRESS: | ||
2660 | return btrfs_ioctl_scrub_progress(root, argp); | ||
2530 | } | 2661 | } |
2531 | 2662 | ||
2532 | return -ENOTTY; | 2663 | return -ENOTTY; |