Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 788f20eb authored by Chris Mason's avatar Chris Mason
Browse files

Btrfs: Add new ioctl to add devices

parent 8e7bf94f
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -551,6 +551,8 @@ struct btrfs_fs_info {
	u64 data_alloc_profile;
	u64 metadata_alloc_profile;
	u64 system_alloc_profile;

	void *bdev_holder;
};

/*
+23 −0
Original line number Diff line number Diff line
@@ -3070,6 +3070,27 @@ static int btrfs_ioctl_defrag(struct file *file)
	return 0;
}

long btrfs_ioctl_add_dev(struct btrfs_root *root, void __user *arg)
{
	struct btrfs_ioctl_vol_args *vol_args;
	int ret;

	vol_args = kmalloc(sizeof(*vol_args), GFP_NOFS);

	if (!vol_args)
		return -ENOMEM;

	if (copy_from_user(vol_args, arg, sizeof(*vol_args))) {
		ret = -EFAULT;
		goto out;
	}
	ret = btrfs_init_new_device(root, vol_args->name);

out:
	kfree(vol_args);
	return ret;
}

long btrfs_ioctl(struct file *file, unsigned int
		cmd, unsigned long arg)
{
@@ -3082,6 +3103,8 @@ long btrfs_ioctl(struct file *file, unsigned int
		return btrfs_ioctl_defrag(file);
	case BTRFS_IOC_RESIZE:
		return btrfs_ioctl_resize(root, (void __user *)arg);
	case BTRFS_IOC_ADD_DEV:
		return btrfs_ioctl_add_dev(root, (void __user *)arg);
	}

	return -ENOTTY;
+6 −0
Original line number Diff line number Diff line
@@ -36,4 +36,10 @@ struct btrfs_ioctl_vol_args {
				   struct btrfs_ioctl_vol_args)
#define BTRFS_IOC_SCAN_DEV _IOW(BTRFS_IOCTL_MAGIC, 4, \
				   struct btrfs_ioctl_vol_args)
#define BTRFS_IOC_ADD_DEV _IOW(BTRFS_IOCTL_MAGIC, 10, \
				   struct btrfs_ioctl_vol_args)
#define BTRFS_IOC_RM_DEV _IOW(BTRFS_IOCTL_MAGIC, 11, \
				   struct btrfs_ioctl_vol_args)
#define BTRFS_IOC_BALANCE _IOW(BTRFS_IOCTL_MAGIC, 12, \
				   struct btrfs_ioctl_vol_args)
#endif
+1 −0
Original line number Diff line number Diff line
@@ -388,6 +388,7 @@ int btrfs_get_sb_bdev(struct file_system_type *fs_type,
			goto error;
		}

		btrfs_sb(s)->fs_info->bdev_holder = fs_type;
		s->s_flags |= MS_ACTIVE;
	}

+75 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <linux/bio.h>
#include <linux/buffer_head.h>
#include <linux/blkdev.h>
#include <linux/random.h>
#include <asm/div64.h>
#include "ctree.h"
#include "extent_map.h"
@@ -592,6 +593,80 @@ int btrfs_add_device(struct btrfs_trans_handle *trans,
	return ret;
}

int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
{
	struct btrfs_trans_handle *trans;
	struct btrfs_device *device;
	struct block_device *bdev;
	struct list_head *cur;
	struct list_head *devices;
	u64 total_bytes;
	int ret = 0;


	bdev = open_bdev_excl(device_path, 0, root->fs_info->bdev_holder);
	if (!bdev) {
		return -EIO;
	}
	mutex_lock(&root->fs_info->fs_mutex);
	trans = btrfs_start_transaction(root, 1);
	devices = &root->fs_info->fs_devices->devices;
	list_for_each(cur, devices) {
		device = list_entry(cur, struct btrfs_device, dev_list);
		if (device->bdev == bdev) {
			ret = -EEXIST;
			goto out;
		}
	}

	device = kzalloc(sizeof(*device), GFP_NOFS);
	if (!device) {
		/* we can safely leave the fs_devices entry around */
		ret = -ENOMEM;
		goto out_close_bdev;
	}

	device->barriers = 1;
	generate_random_uuid(device->uuid);
	spin_lock_init(&device->io_lock);
	device->name = kstrdup(device_path, GFP_NOFS);
	if (!device->name) {
		kfree(device);
		goto out_close_bdev;
	}
	device->io_width = root->sectorsize;
	device->io_align = root->sectorsize;
	device->sector_size = root->sectorsize;
	device->total_bytes = i_size_read(bdev->bd_inode);
	device->dev_root = root->fs_info->dev_root;
	device->bdev = bdev;

	ret = btrfs_add_device(trans, root, device);
	if (ret)
		goto out_close_bdev;

	total_bytes = btrfs_super_total_bytes(&root->fs_info->super_copy);
	btrfs_set_super_total_bytes(&root->fs_info->super_copy,
				    total_bytes + device->total_bytes);

	total_bytes = btrfs_super_num_devices(&root->fs_info->super_copy);
	btrfs_set_super_num_devices(&root->fs_info->super_copy,
				    total_bytes + 1);

	list_add(&device->dev_list, &root->fs_info->fs_devices->devices);
	list_add(&device->dev_alloc_list,
		 &root->fs_info->fs_devices->alloc_list);
	root->fs_info->fs_devices->num_devices++;
out:
	btrfs_end_transaction(trans, root);
	mutex_unlock(&root->fs_info->fs_mutex);
	return ret;

out_close_bdev:
	close_bdev_excl(bdev);
	goto out;
}

int btrfs_update_device(struct btrfs_trans_handle *trans,
			struct btrfs_device *device)
{
Loading