aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r--fs/btrfs/ioctl.c131
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
1806static 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
1833static 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
1867out:
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
1806static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, 1875static 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
2537static 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
2559static 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
2567static 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
2468long btrfs_ioctl(struct file *file, unsigned int 2589long 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;