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

Commit dfe25020 authored by Chris Mason's avatar Chris Mason
Browse files

Btrfs: Add mount -o degraded to allow mounts to continue with missing devices

parent 1259ab75
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -657,6 +657,7 @@ struct btrfs_root {
#define BTRFS_MOUNT_NODATACOW		(1 << 1)
#define BTRFS_MOUNT_NOBARRIER		(1 << 2)
#define BTRFS_MOUNT_SSD			(1 << 3)
#define BTRFS_MOUNT_DEGRADED		(1 << 4)

#define btrfs_clear_opt(o, opt)		((o) &= ~BTRFS_MOUNT_##opt)
#define btrfs_set_opt(o, opt)		((o) |= BTRFS_MOUNT_##opt)
@@ -1606,4 +1607,6 @@ int btrfs_delete_xattrs(struct btrfs_trans_handle *trans,
			struct btrfs_root *root, struct inode *inode);
/* super.c */
u64 btrfs_parse_size(char *str);
int btrfs_parse_options(char *options, struct btrfs_root *root,
			char **subvol_name);
#endif
+29 −20
Original line number Diff line number Diff line
@@ -614,21 +614,6 @@ int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize,
	return ret;
}

static int close_all_devices(struct btrfs_fs_info *fs_info)
{
	struct list_head *list;
	struct list_head *next;
	struct btrfs_device *device;

	list = &fs_info->fs_devices->devices;
	list_for_each(next, list) {
		device = list_entry(next, struct btrfs_device, dev_list);
		close_bdev_excl(device->bdev);
		device->bdev = NULL;
	}
	return 0;
}

struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root,
					    u64 bytenr, u32 blocksize)
{
@@ -927,6 +912,8 @@ static int btrfs_congested_fn(void *congested_data, int bdi_bits)

	list_for_each(cur, &info->fs_devices->devices) {
		device = list_entry(cur, struct btrfs_device, dev_list);
		if (!device->bdev)
			continue;
		bdi = blk_get_backing_dev_info(device->bdev);
		if (bdi && bdi_congested(bdi, bdi_bits)) {
			ret = 1;
@@ -1140,7 +1127,8 @@ static void btrfs_async_submit_work(struct work_struct *work)
}

struct btrfs_root *open_ctree(struct super_block *sb,
			      struct btrfs_fs_devices *fs_devices)
			      struct btrfs_fs_devices *fs_devices,
			      char *options)
{
	u32 sectorsize;
	u32 nodesize;
@@ -1276,12 +1264,19 @@ struct btrfs_root *open_ctree(struct super_block *sb,
	if (!btrfs_super_root(disk_super))
		goto fail_sb_buffer;

	if (btrfs_super_num_devices(disk_super) != fs_devices->num_devices) {
	btrfs_parse_options(options, tree_root, NULL);

	if (btrfs_super_num_devices(disk_super) > fs_devices->num_devices) {
		printk("Btrfs: wanted %llu devices, but found %llu\n",
		       (unsigned long long)btrfs_super_num_devices(disk_super),
		       (unsigned long long)fs_devices->num_devices);
		if (btrfs_test_opt(tree_root, DEGRADED))
			printk("continuing in degraded mode\n");
		else {
			goto fail_sb_buffer;
		}
	}

	fs_info->bdi.ra_pages *= btrfs_super_num_devices(disk_super);

	nodesize = btrfs_super_nodesize(disk_super);
@@ -1329,6 +1324,8 @@ struct btrfs_root *open_ctree(struct super_block *sb,
	ret = btrfs_read_chunk_tree(chunk_root);
	BUG_ON(ret);

	btrfs_close_extra_devices(fs_devices);

	blocksize = btrfs_level_size(tree_root,
				     btrfs_super_root_level(disk_super));

@@ -1374,7 +1371,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
fail_iput:
	iput(fs_info->btree_inode);
fail:
	close_all_devices(fs_info);
	btrfs_close_devices(fs_info->fs_devices);
	btrfs_mapping_tree_free(&fs_info->mapping_tree);

	kfree(extent_root);
@@ -1429,6 +1426,13 @@ int write_all_supers(struct btrfs_root *root)
	dev_item = &sb->dev_item;
	list_for_each(cur, head) {
		dev = list_entry(cur, struct btrfs_device, dev_list);
		if (!dev->bdev) {
			total_errors++;
			continue;
		}
		if (!dev->in_fs_metadata)
			continue;

		btrfs_set_stack_device_type(dev_item, dev->type);
		btrfs_set_stack_device_id(dev_item, dev->devid);
		btrfs_set_stack_device_total_bytes(dev_item, dev->total_bytes);
@@ -1482,6 +1486,11 @@ int write_all_supers(struct btrfs_root *root)

	list_for_each(cur, head) {
		dev = list_entry(cur, struct btrfs_device, dev_list);
		if (!dev->bdev)
			continue;
		if (!dev->in_fs_metadata)
			continue;

		BUG_ON(!dev->pending_io);
		bh = dev->pending_io;
		wait_on_buffer(bh);
@@ -1631,7 +1640,7 @@ int close_ctree(struct btrfs_root *root)
		kfree(hasher);
	}
#endif
	close_all_devices(fs_info);
	btrfs_close_devices(fs_info->fs_devices);
	btrfs_mapping_tree_free(&fs_info->mapping_tree);

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
+2 −1
Original line number Diff line number Diff line
@@ -33,7 +33,8 @@ struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root,
int clean_tree_block(struct btrfs_trans_handle *trans,
		     struct btrfs_root *root, struct extent_buffer *buf);
struct btrfs_root *open_ctree(struct super_block *sb,
			      struct btrfs_fs_devices *fs_devices);
			      struct btrfs_fs_devices *fs_devices,
			      char *options);
int close_ctree(struct btrfs_root *root);
int write_ctree_super(struct btrfs_trans_handle *trans,
		      struct btrfs_root *root);
+15 −10
Original line number Diff line number Diff line
@@ -65,11 +65,13 @@ static void btrfs_put_super (struct super_block * sb)
}

enum {
	Opt_subvol, Opt_nodatasum, Opt_nodatacow, Opt_max_extent,
	Opt_max_inline, Opt_alloc_start, Opt_nobarrier, Opt_ssd, Opt_err,
	Opt_degraded, Opt_subvol, Opt_nodatasum, Opt_nodatacow,
	Opt_max_extent, Opt_max_inline, Opt_alloc_start, Opt_nobarrier,
	Opt_ssd, Opt_err,
};

static match_table_t tokens = {
	{Opt_degraded, "degraded"},
	{Opt_subvol, "subvol=%s"},
	{Opt_nodatasum, "nodatasum"},
	{Opt_nodatacow, "nodatacow"},
@@ -106,8 +108,7 @@ u64 btrfs_parse_size(char *str)
	return res;
}

static int parse_options (char * options,
			  struct btrfs_root *root,
int btrfs_parse_options(char *options, struct btrfs_root *root,
			char **subvol_name)
{
	char * p;
@@ -135,6 +136,12 @@ static int parse_options (char * options,

		token = match_token(p, tokens, args);
		switch (token) {
		case Opt_degraded:
			if (info) {
				printk("btrfs: allowing degraded mounts\n");
				btrfs_set_opt(info->mount_opt, DEGRADED);
			}
			break;
		case Opt_subvol:
			if (subvol_name) {
				*subvol_name = match_strdup(&args[0]);
@@ -234,7 +241,7 @@ static int btrfs_fill_super(struct super_block * sb,
	sb->s_xattr = btrfs_xattr_handlers;
	sb->s_time_gran = 1;

	tree_root = open_ctree(sb, fs_devices);
	tree_root = open_ctree(sb, fs_devices, (char *)data);

	if (IS_ERR(tree_root)) {
		printk("btrfs: open_ctree failed\n");
@@ -267,8 +274,6 @@ static int btrfs_fill_super(struct super_block * sb,
		goto fail_close;
	}

	parse_options((char *)data, tree_root, NULL);

	/* this does the super kobj at the same time */
	err = btrfs_sysfs_add_super(tree_root->fs_info);
	if (err)
@@ -341,7 +346,7 @@ int btrfs_get_sb_bdev(struct file_system_type *fs_type,
	if (error)
		return error;

	bdev = fs_devices->lowest_bdev;
	bdev = fs_devices->latest_bdev;
	btrfs_lock_volumes();
	s = sget(fs_type, btrfs_test_super, set_anon_super, fs_devices);
	btrfs_unlock_volumes();
@@ -411,7 +416,7 @@ static int btrfs_get_sb(struct file_system_type *fs_type,
	int ret;
	char *subvol_name = NULL;

	parse_options((char *)data, NULL, &subvol_name);
	btrfs_parse_options((char *)data, NULL, &subvol_name);
	ret = btrfs_get_sb_bdev(fs_type, flags, dev_name, data, mnt,
			subvol_name ? subvol_name : "default");
	if (subvol_name)
+201 −78
Original line number Diff line number Diff line
@@ -73,6 +73,7 @@ int btrfs_cleanup_fs_uuids(void)
				close_bdev_excl(dev->bdev);
			}
			list_del(&dev->dev_list);
			kfree(dev->name);
			kfree(dev);
		}
	}
@@ -127,7 +128,6 @@ static int device_list_add(const char *path,
		memcpy(fs_devices->fsid, disk_super->fsid, BTRFS_FSID_SIZE);
		fs_devices->latest_devid = devid;
		fs_devices->latest_trans = found_transid;
		fs_devices->lowest_devid = (u64)-1;
		fs_devices->num_devices = 0;
		device = NULL;
	} else {
@@ -159,13 +159,35 @@ static int device_list_add(const char *path,
		fs_devices->latest_devid = devid;
		fs_devices->latest_trans = found_transid;
	}
	if (fs_devices->lowest_devid > devid) {
		fs_devices->lowest_devid = devid;
	}
	*fs_devices_ret = fs_devices;
	return 0;
}

int btrfs_close_extra_devices(struct btrfs_fs_devices *fs_devices)
{
	struct list_head *head = &fs_devices->devices;
	struct list_head *cur;
	struct btrfs_device *device;

	mutex_lock(&uuid_mutex);
again:
	list_for_each(cur, head) {
		device = list_entry(cur, struct btrfs_device, dev_list);
		if (!device->in_fs_metadata) {
printk("getting rid of extra dev %s\n", device->name);
			if (device->bdev)
				close_bdev_excl(device->bdev);
			list_del(&device->dev_list);
			list_del(&device->dev_alloc_list);
			fs_devices->num_devices--;
			kfree(device->name);
			kfree(device);
			goto again;
		}
	}
	mutex_unlock(&uuid_mutex);
	return 0;
}
int btrfs_close_devices(struct btrfs_fs_devices *fs_devices)
{
	struct list_head *head = &fs_devices->devices;
@@ -179,6 +201,7 @@ int btrfs_close_devices(struct btrfs_fs_devices *fs_devices)
			close_bdev_excl(device->bdev);
		}
		device->bdev = NULL;
		device->in_fs_metadata = 0;
	}
	mutex_unlock(&uuid_mutex);
	return 0;
@@ -199,6 +222,9 @@ int btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
		if (device->bdev)
			continue;

		if (!device->name)
			continue;

		bdev = open_bdev_excl(device->name, flags, holder);

		if (IS_ERR(bdev)) {
@@ -209,10 +235,8 @@ int btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
		set_blocksize(bdev, 4096);
		if (device->devid == fs_devices->latest_devid)
			fs_devices->latest_bdev = bdev;
		if (device->devid == fs_devices->lowest_devid) {
			fs_devices->lowest_bdev = bdev;
		}
		device->bdev = bdev;
		device->in_fs_metadata = 0;

	}
	mutex_unlock(&uuid_mutex);
@@ -439,6 +463,7 @@ int btrfs_free_dev_extent(struct btrfs_trans_handle *trans,
	}
	BUG_ON(ret);

	if (device->bytes_used > 0)
		device->bytes_used -= btrfs_dev_extent_length(leaf, extent);
	ret = btrfs_del_item(trans, root, path);
	BUG_ON(ret);
@@ -460,6 +485,7 @@ int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans,
	struct extent_buffer *leaf;
	struct btrfs_key key;

	WARN_ON(!device->in_fs_metadata);
	path = btrfs_alloc_path();
	if (!path)
		return -ENOMEM;
@@ -674,8 +700,6 @@ static int btrfs_rm_dev_item(struct btrfs_root *root,

	next_dev = list_entry(fs_devices->devices.next, struct btrfs_device,
			      dev_list);
	if (bdev == fs_devices->lowest_bdev)
		fs_devices->lowest_bdev = next_dev->bdev;
	if (bdev == root->fs_info->sb->s_bdev)
		root->fs_info->sb->s_bdev = next_dev->bdev;
	if (bdev == fs_devices->latest_bdev)
@@ -698,7 +722,7 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
{
	struct btrfs_device *device;
	struct block_device *bdev;
	struct buffer_head *bh;
	struct buffer_head *bh = NULL;
	struct btrfs_super_block *disk_super;
	u64 all_avail;
	u64 devid;
@@ -712,20 +736,44 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
		root->fs_info->avail_metadata_alloc_bits;

	if ((all_avail & BTRFS_BLOCK_GROUP_RAID10) &&
	    root->fs_info->fs_devices->num_devices <= 4) {
	    btrfs_super_num_devices(&root->fs_info->super_copy) <= 4) {
		printk("btrfs: unable to go below four devices on raid10\n");
		ret = -EINVAL;
		goto out;
	}

	if ((all_avail & BTRFS_BLOCK_GROUP_RAID1) &&
	    root->fs_info->fs_devices->num_devices <= 2) {
	    btrfs_super_num_devices(&root->fs_info->super_copy) <= 2) {
		printk("btrfs: unable to go below two devices on raid1\n");
		ret = -EINVAL;
		goto out;
	}

	bdev = open_bdev_excl(device_path, 0, root->fs_info->bdev_holder);
	if (strcmp(device_path, "missing") == 0) {
		struct list_head *cur;
		struct list_head *devices;
		struct btrfs_device *tmp;

		device = NULL;
		devices = &root->fs_info->fs_devices->devices;
		list_for_each(cur, devices) {
			tmp = list_entry(cur, struct btrfs_device, dev_list);
			if (tmp->in_fs_metadata && !tmp->bdev) {
				device = tmp;
				break;
			}
		}
		bdev = NULL;
		bh = NULL;
		disk_super = NULL;
		if (!device) {
			printk("btrfs: no missing devices found to remove\n");
			goto out;
		}

	} else {
		bdev = open_bdev_excl(device_path, 0,
				      root->fs_info->bdev_holder);
		if (IS_ERR(bdev)) {
			ret = PTR_ERR(bdev);
			goto out;
@@ -742,7 +790,8 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
			ret = -ENOENT;
			goto error_brelse;
		}
	if (memcmp(disk_super->fsid, root->fs_info->fsid, BTRFS_FSID_SIZE)) {
		if (memcmp(disk_super->fsid, root->fs_info->fsid,
			   BTRFS_FSID_SIZE)) {
			ret = -ENOENT;
			goto error_brelse;
		}
@@ -753,6 +802,7 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
			goto error_brelse;
		}

	}
	root->fs_info->fs_devices->num_devices--;

	ret = btrfs_shrink_device(device, 0);
@@ -764,19 +814,25 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
	if (ret)
		goto error_brelse;

	/* make sure this device isn't detected as part of the FS anymore */
	if (bh) {
		/* make sure this device isn't detected as part of
		 * the FS anymore
		 */
		memset(&disk_super->magic, 0, sizeof(disk_super->magic));
		set_buffer_dirty(bh);
		sync_dirty_buffer(bh);

		brelse(bh);
	}

	if (device->bdev) {
		/* one close for the device struct or super_block */
		close_bdev_excl(device->bdev);

	}
	if (bdev) {
		/* one close for us */
	close_bdev_excl(device->bdev);

		close_bdev_excl(bdev);
	}
	kfree(device->name);
	kfree(device);
	ret = 0;
@@ -785,6 +841,7 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
error_brelse:
	brelse(bh);
error_close:
	if (bdev)
		close_bdev_excl(bdev);
out:
	mutex_unlock(&uuid_mutex);
@@ -839,6 +896,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
	device->total_bytes = i_size_read(bdev->bd_inode);
	device->dev_root = root->fs_info->dev_root;
	device->bdev = bdev;
	device->in_fs_metadata = 1;

	ret = btrfs_add_device(trans, root, device);
	if (ret)
@@ -1041,9 +1099,11 @@ int btrfs_relocate_chunk(struct btrfs_root *root,
					    map->stripes[i].physical);
		BUG_ON(ret);

		if (map->stripes[i].dev) {
			ret = btrfs_update_device(trans, map->stripes[i].dev);
			BUG_ON(ret);
		}
	}
	ret = btrfs_free_chunk(trans, root, chunk_tree, chunk_objectid,
			       chunk_offset);

@@ -1415,10 +1475,13 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
	while(index < num_stripes) {
		device = list_entry(cur, struct btrfs_device, dev_alloc_list);

		if (device->total_bytes > device->bytes_used)
			avail = device->total_bytes - device->bytes_used;
		else
			avail = 0;
		cur = cur->next;

		if (avail >= min_free) {
		if (device->in_fs_metadata && avail >= min_free) {
			u64 ignored_start = 0;
			ret = find_free_dev_extent(trans, device, path,
						   min_free,
@@ -1430,7 +1493,7 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
				if (type & BTRFS_BLOCK_GROUP_DUP)
					index++;
			}
		} else if (avail > max_avail)
		} else if (device->in_fs_metadata && avail > max_avail)
			max_avail = avail;
		if (cur == dev_list)
			break;
@@ -1610,6 +1673,22 @@ int btrfs_num_copies(struct btrfs_mapping_tree *map_tree, u64 logical, u64 len)
	return ret;
}

static int find_live_mirror(struct map_lookup *map, int first, int num,
			    int optimal)
{
	int i;
	if (map->stripes[optimal].dev->bdev)
		return optimal;
	for (i = first; i < first + num; i++) {
		if (map->stripes[i].dev->bdev)
			return i;
	}
	/* we couldn't find one that doesn't fail.  Just return something
	 * and the io error handling code will clean up eventually
	 */
	return optimal;
}

static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
			     u64 logical, u64 *length,
			     struct btrfs_multi_bio **multi_ret,
@@ -1712,8 +1791,11 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
			num_stripes = map->num_stripes;
		else if (mirror_num)
			stripe_index = mirror_num - 1;
		else
			stripe_index = current->pid % map->num_stripes;
		else {
			stripe_index = find_live_mirror(map, 0,
					    map->num_stripes,
					    current->pid % map->num_stripes);
		}

	} else if (map->type & BTRFS_BLOCK_GROUP_DUP) {
		if (rw & (1 << BIO_RW))
@@ -1731,8 +1813,11 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
			num_stripes = map->sub_stripes;
		else if (mirror_num)
			stripe_index += mirror_num - 1;
		else
			stripe_index += current->pid % map->sub_stripes;
		else {
			stripe_index = find_live_mirror(map, stripe_index,
					      map->sub_stripes, stripe_index +
					      current->pid % map->sub_stripes);
		}
	} else {
		/*
		 * after this do_div call, stripe_nr is the number of stripes
@@ -1749,10 +1834,12 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
			struct backing_dev_info *bdi;

			device = map->stripes[stripe_index].dev;
			if (device->bdev) {
				bdi = blk_get_backing_dev_info(device->bdev);
				if (bdi->unplug_io_fn) {
					bdi->unplug_io_fn(bdi, unplug_page);
				}
			}
		} else {
			multi->stripes[i].physical =
				map->stripes[stripe_index].physical +
@@ -1880,12 +1967,21 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio,
		}
		bio->bi_sector = multi->stripes[dev_nr].physical >> 9;
		dev = multi->stripes[dev_nr].dev;

		if (dev && dev->bdev) {
			bio->bi_bdev = dev->bdev;
			spin_lock(&dev->io_lock);
			dev->total_ios++;
			spin_unlock(&dev->io_lock);
			submit_bio(rw, bio);
		} else {
			bio->bi_bdev = root->fs_info->fs_devices->latest_bdev;
			bio->bi_sector = logical >> 9;
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23)
			bio_endio(bio, bio->bi_size, -EIO);
#else
			bio_endio(bio, -EIO);
#endif
		}
		dev_nr++;
	}
	if (total_devs == 1)
@@ -1901,6 +1997,27 @@ struct btrfs_device *btrfs_find_device(struct btrfs_root *root, u64 devid,
	return __find_device(head, devid, uuid);
}

static struct btrfs_device *add_missing_dev(struct btrfs_root *root,
					    u64 devid, u8 *dev_uuid)
{
	struct btrfs_device *device;
	struct btrfs_fs_devices *fs_devices = root->fs_info->fs_devices;

	device = kzalloc(sizeof(*device), GFP_NOFS);
	list_add(&device->dev_list,
		 &fs_devices->devices);
	list_add(&device->dev_alloc_list,
		 &fs_devices->alloc_list);
	device->barriers = 1;
	device->dev_root = root->fs_info->dev_root;
	device->devid = devid;
	fs_devices->num_devices++;
	spin_lock_init(&device->io_lock);
	memcpy(device->uuid, dev_uuid, BTRFS_UUID_SIZE);
	return device;
}


static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
			  struct extent_buffer *leaf,
			  struct btrfs_chunk *chunk)
@@ -1965,12 +2082,23 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
				   btrfs_stripe_dev_uuid_nr(chunk, i),
				   BTRFS_UUID_SIZE);
		map->stripes[i].dev = btrfs_find_device(root, devid, uuid);

		if (!map->stripes[i].dev && !btrfs_test_opt(root, DEGRADED)) {
			kfree(map);
			free_extent_map(em);
			return -EIO;
		}
		if (!map->stripes[i].dev) {
			map->stripes[i].dev =
				add_missing_dev(root, devid, uuid);
			if (!map->stripes[i].dev) {
				kfree(map);
				free_extent_map(em);
				return -EIO;
			}
		}
		map->stripes[i].dev->in_fs_metadata = 1;
	}

	spin_lock(&map_tree->map_tree.lock);
	ret = add_extent_mapping(&map_tree->map_tree, em);
@@ -2016,20 +2144,15 @@ static int read_one_dev(struct btrfs_root *root,
			   BTRFS_UUID_SIZE);
	device = btrfs_find_device(root, devid, dev_uuid);
	if (!device) {
		printk("warning devid %Lu not found already\n", devid);
		device = kzalloc(sizeof(*device), GFP_NOFS);
		printk("warning devid %Lu missing\n", devid);
		device = add_missing_dev(root, devid, dev_uuid);
		if (!device)
			return -ENOMEM;
		list_add(&device->dev_list,
			 &root->fs_info->fs_devices->devices);
		list_add(&device->dev_alloc_list,
			 &root->fs_info->fs_devices->alloc_list);
		device->barriers = 1;
		spin_lock_init(&device->io_lock);
	}

	fill_device_from_item(leaf, dev_item, device);
	device->dev_root = root->fs_info->dev_root;
	device->in_fs_metadata = 1;
	ret = 0;
#if 0
	ret = btrfs_open_device(device);
Loading