Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 346690
b: refs/heads/master
c: 63a212a
h: refs/heads/master
v: v3
  • Loading branch information
Stefan Behrens authored and Josef Bacik committed Dec 12, 2012
1 parent 1524084 commit 5e6ceee
Show file tree
Hide file tree
Showing 8 changed files with 55 additions and 19 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 5ac00addc7ac09110995fe967071d191b5981cc1
refs/heads/master: 63a212abc2315972b245f93cb11ae3acf3c0b513
2 changes: 1 addition & 1 deletion trunk/fs/btrfs/ctree.h
Original file line number Diff line number Diff line change
Expand Up @@ -3649,7 +3649,7 @@ int btrfs_reloc_post_snapshot(struct btrfs_trans_handle *trans,
/* scrub.c */
int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start,
u64 end, struct btrfs_scrub_progress *progress,
int readonly);
int readonly, int is_dev_replace);
void btrfs_scrub_pause(struct btrfs_root *root);
void btrfs_scrub_pause_super(struct btrfs_root *root);
void btrfs_scrub_continue(struct btrfs_root *root);
Expand Down
3 changes: 2 additions & 1 deletion trunk/fs/btrfs/extent-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -7468,7 +7468,8 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr)
* check to make sure we can actually find a chunk with enough
* space to fit our block group in.
*/
if (device->total_bytes > device->bytes_used + min_free) {
if (device->total_bytes > device->bytes_used + min_free &&
!device->is_tgtdev_for_dev_replace) {
ret = find_free_dev_extent(device, min_free,
&dev_offset, NULL);
if (!ret)
Expand Down
8 changes: 7 additions & 1 deletion trunk/fs/btrfs/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1375,6 +1375,11 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root,
}
}

if (device->is_tgtdev_for_dev_replace) {
ret = -EINVAL;
goto out_free;
}

old_size = device->total_bytes;

if (mod < 0) {
Expand Down Expand Up @@ -3102,7 +3107,8 @@ static long btrfs_ioctl_scrub(struct btrfs_root *root, void __user *arg)
return PTR_ERR(sa);

ret = btrfs_scrub_dev(root->fs_info, sa->devid, sa->start, sa->end,
&sa->progress, sa->flags & BTRFS_SCRUB_READONLY);
&sa->progress, sa->flags & BTRFS_SCRUB_READONLY,
0);

if (copy_to_user(arg, sa, sizeof(*sa)))
ret = -EFAULT;
Expand Down
14 changes: 9 additions & 5 deletions trunk/fs/btrfs/scrub.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ struct scrub_ctx {
u32 sectorsize;
u32 nodesize;
u32 leafsize;

int is_dev_replace;

/*
* statistics
*/
Expand Down Expand Up @@ -284,7 +287,7 @@ static noinline_for_stack void scrub_free_ctx(struct scrub_ctx *sctx)
}

static noinline_for_stack
struct scrub_ctx *scrub_setup_ctx(struct btrfs_device *dev)
struct scrub_ctx *scrub_setup_ctx(struct btrfs_device *dev, int is_dev_replace)
{
struct scrub_ctx *sctx;
int i;
Expand All @@ -296,6 +299,7 @@ struct scrub_ctx *scrub_setup_ctx(struct btrfs_device *dev)
sctx = kzalloc(sizeof(*sctx), GFP_NOFS);
if (!sctx)
goto nomem;
sctx->is_dev_replace = is_dev_replace;
sctx->pages_per_bio = pages_per_bio;
sctx->curr = -1;
sctx->dev_root = dev->dev_root;
Expand Down Expand Up @@ -2293,7 +2297,7 @@ static noinline_for_stack void scrub_workers_put(struct btrfs_fs_info *fs_info)

int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start,
u64 end, struct btrfs_scrub_progress *progress,
int readonly)
int readonly, int is_dev_replace)
{
struct scrub_ctx *sctx;
int ret;
Expand Down Expand Up @@ -2356,14 +2360,14 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start,

mutex_lock(&fs_info->fs_devices->device_list_mutex);
dev = btrfs_find_device(fs_info, devid, NULL, NULL);
if (!dev || dev->missing) {
if (!dev || (dev->missing && !is_dev_replace)) {
mutex_unlock(&fs_info->fs_devices->device_list_mutex);
scrub_workers_put(fs_info);
return -ENODEV;
}
mutex_lock(&fs_info->scrub_lock);

if (!dev->in_fs_metadata) {
if (!dev->in_fs_metadata || dev->is_tgtdev_for_dev_replace) {
mutex_unlock(&fs_info->scrub_lock);
mutex_unlock(&fs_info->fs_devices->device_list_mutex);
scrub_workers_put(fs_info);
Expand All @@ -2376,7 +2380,7 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start,
scrub_workers_put(fs_info);
return -EINPROGRESS;
}
sctx = scrub_setup_ctx(dev);
sctx = scrub_setup_ctx(dev, is_dev_replace);
if (IS_ERR(sctx)) {
mutex_unlock(&fs_info->scrub_lock);
mutex_unlock(&fs_info->fs_devices->device_list_mutex);
Expand Down
3 changes: 2 additions & 1 deletion trunk/fs/btrfs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -1354,7 +1354,8 @@ static int btrfs_calc_avail_data_space(struct btrfs_root *root, u64 *free_bytes)
min_stripe_size = BTRFS_STRIPE_LEN;

list_for_each_entry(device, &fs_devices->devices, dev_list) {
if (!device->in_fs_metadata || !device->bdev)
if (!device->in_fs_metadata || !device->bdev ||
device->is_tgtdev_for_dev_replace)
continue;

avail_space = device->total_bytes - device->bytes_used;
Expand Down
41 changes: 32 additions & 9 deletions trunk/fs/btrfs/volumes.c
Original file line number Diff line number Diff line change
Expand Up @@ -518,8 +518,9 @@ void btrfs_close_extra_devices(struct btrfs_fs_devices *fs_devices)
/* This is the initialized path, it is safe to release the devices. */
list_for_each_entry_safe(device, next, &fs_devices->devices, dev_list) {
if (device->in_fs_metadata) {
if (!latest_transid ||
device->generation > latest_transid) {
if (!device->is_tgtdev_for_dev_replace &&
(!latest_transid ||
device->generation > latest_transid)) {
latest_devid = device->devid;
latest_transid = device->generation;
latest_bdev = device->bdev;
Expand Down Expand Up @@ -814,7 +815,7 @@ int btrfs_account_dev_extents_size(struct btrfs_device *device, u64 start,

*length = 0;

if (start >= device->total_bytes)
if (start >= device->total_bytes || device->is_tgtdev_for_dev_replace)
return 0;

path = btrfs_alloc_path();
Expand Down Expand Up @@ -931,7 +932,7 @@ int find_free_dev_extent(struct btrfs_device *device, u64 num_bytes,
max_hole_size = 0;
hole_size = 0;

if (search_start >= search_end) {
if (search_start >= search_end || device->is_tgtdev_for_dev_replace) {
ret = -ENOSPC;
goto error;
}
Expand Down Expand Up @@ -1114,6 +1115,7 @@ int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans,
struct btrfs_key key;

WARN_ON(!device->in_fs_metadata);
WARN_ON(device->is_tgtdev_for_dev_replace);
path = btrfs_alloc_path();
if (!path)
return -ENOMEM;
Expand Down Expand Up @@ -1375,7 +1377,9 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
* is held.
*/
list_for_each_entry(tmp, devices, dev_list) {
if (tmp->in_fs_metadata && !tmp->bdev) {
if (tmp->in_fs_metadata &&
!tmp->is_tgtdev_for_dev_replace &&
!tmp->bdev) {
device = tmp;
break;
}
Expand Down Expand Up @@ -1406,6 +1410,12 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
}
}

if (device->is_tgtdev_for_dev_replace) {
pr_err("btrfs: unable to remove the dev_replace target dev\n");
ret = -EINVAL;
goto error_brelse;
}

if (device->writeable && root->fs_info->fs_devices->rw_devices == 1) {
printk(KERN_ERR "btrfs: unable to remove the only writeable "
"device\n");
Expand All @@ -1425,6 +1435,11 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
if (ret)
goto error_undo;

/*
* TODO: the superblock still includes this device in its num_devices
* counter although write_all_supers() is not locked out. This
* could give a filesystem state which requires a degraded mount.
*/
ret = btrfs_rm_dev_item(root->fs_info->chunk_root, device);
if (ret)
goto error_undo;
Expand Down Expand Up @@ -1808,6 +1823,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
device->dev_root = root->fs_info->dev_root;
device->bdev = bdev;
device->in_fs_metadata = 1;
device->is_tgtdev_for_dev_replace = 0;
device->mode = FMODE_EXCL;
set_blocksize(device->bdev, 4096);

Expand Down Expand Up @@ -1971,7 +1987,8 @@ static int __btrfs_grow_device(struct btrfs_trans_handle *trans,

if (!device->writeable)
return -EACCES;
if (new_size <= device->total_bytes)
if (new_size <= device->total_bytes ||
device->is_tgtdev_for_dev_replace)
return -EINVAL;

btrfs_set_super_total_bytes(super_copy, old_total + diff);
Expand Down Expand Up @@ -2600,7 +2617,8 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info)
size_to_free = div_factor(old_size, 1);
size_to_free = min(size_to_free, (u64)1 * 1024 * 1024);
if (!device->writeable ||
device->total_bytes - device->bytes_used > size_to_free)
device->total_bytes - device->bytes_used > size_to_free ||
device->is_tgtdev_for_dev_replace)
continue;

ret = btrfs_shrink_device(device, old_size - size_to_free);
Expand Down Expand Up @@ -3132,6 +3150,9 @@ int btrfs_shrink_device(struct btrfs_device *device, u64 new_size)
u64 old_size = device->total_bytes;
u64 diff = device->total_bytes - new_size;

if (device->is_tgtdev_for_dev_replace)
return -EINVAL;

path = btrfs_alloc_path();
if (!path)
return -ENOMEM;
Expand Down Expand Up @@ -3401,7 +3422,8 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
continue;
}

if (!device->in_fs_metadata)
if (!device->in_fs_metadata ||
device->is_tgtdev_for_dev_replace)
continue;

if (device->total_bytes > device->bytes_used)
Expand Down Expand Up @@ -4612,6 +4634,7 @@ static void fill_device_from_item(struct extent_buffer *leaf,
device->io_align = btrfs_device_io_align(leaf, dev_item);
device->io_width = btrfs_device_io_width(leaf, dev_item);
device->sector_size = btrfs_device_sector_size(leaf, dev_item);
device->is_tgtdev_for_dev_replace = 0;

ptr = (unsigned long)btrfs_device_uuid(dev_item);
read_extent_buffer(leaf, device->uuid, ptr, BTRFS_UUID_SIZE);
Expand Down Expand Up @@ -4722,7 +4745,7 @@ static int read_one_dev(struct btrfs_root *root,
fill_device_from_item(leaf, dev_item, device);
device->dev_root = root->fs_info->dev_root;
device->in_fs_metadata = 1;
if (device->writeable) {
if (device->writeable && !device->is_tgtdev_for_dev_replace) {
device->fs_devices->total_rw_bytes += device->total_bytes;
spin_lock(&root->fs_info->free_chunk_lock);
root->fs_info->free_chunk_space += device->total_bytes -
Expand Down
1 change: 1 addition & 0 deletions trunk/fs/btrfs/volumes.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ struct btrfs_device {
int in_fs_metadata;
int missing;
int can_discard;
int is_tgtdev_for_dev_replace;

spinlock_t io_lock;

Expand Down

0 comments on commit 5e6ceee

Please sign in to comment.