aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/volumes.c
diff options
context:
space:
mode:
authorJosef Bacik <josef@redhat.com>2011-08-04 10:52:27 -0400
committerChris Mason <chris.mason@oracle.com>2011-08-16 21:09:15 -0400
commitd5e2003c2bcda93a8f2e668eb4642d70c9c38301 (patch)
tree336234b9d9a144f180bc51738f55fef7f743b725 /fs/btrfs/volumes.c
parent2ab1ba68aeaecd41c4b34f0eaf1d70a37367fb1a (diff)
Btrfs: detect wether a device supports discard
We have a problem where if a user specifies discard but doesn't actually support it we will return EOPNOTSUPP from btrfs_discard_extent. This is a problem because this gets called (in a fashion) from the tree log recovery code, which has a nice little BUG_ON(ret) after it, which causes us to fail the tree log replay. So instead detect wether our devices support discard when we're adding them and then don't issue discards if we know that the device doesn't support it. And just for good measure set ret = 0 in btrfs_issue_discard just in case we still get EOPNOTSUPP so we don't screw anybody up like this again. Thanks, Signed-off-by: Josef Bacik <josef@redhat.com> Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r--fs/btrfs/volumes.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 3c5f2fcd82c1..a595f8775c37 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -517,6 +517,9 @@ static int __btrfs_close_devices(struct btrfs_fs_devices *fs_devices)
517 fs_devices->rw_devices--; 517 fs_devices->rw_devices--;
518 } 518 }
519 519
520 if (device->can_discard)
521 fs_devices->num_can_discard--;
522
520 new_device = kmalloc(sizeof(*new_device), GFP_NOFS); 523 new_device = kmalloc(sizeof(*new_device), GFP_NOFS);
521 BUG_ON(!new_device); 524 BUG_ON(!new_device);
522 memcpy(new_device, device, sizeof(*new_device)); 525 memcpy(new_device, device, sizeof(*new_device));
@@ -525,6 +528,7 @@ static int __btrfs_close_devices(struct btrfs_fs_devices *fs_devices)
525 new_device->bdev = NULL; 528 new_device->bdev = NULL;
526 new_device->writeable = 0; 529 new_device->writeable = 0;
527 new_device->in_fs_metadata = 0; 530 new_device->in_fs_metadata = 0;
531 new_device->can_discard = 0;
528 list_replace_rcu(&device->dev_list, &new_device->dev_list); 532 list_replace_rcu(&device->dev_list, &new_device->dev_list);
529 533
530 call_rcu(&device->rcu, free_device); 534 call_rcu(&device->rcu, free_device);
@@ -564,6 +568,7 @@ int btrfs_close_devices(struct btrfs_fs_devices *fs_devices)
564static int __btrfs_open_devices(struct btrfs_fs_devices *fs_devices, 568static int __btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
565 fmode_t flags, void *holder) 569 fmode_t flags, void *holder)
566{ 570{
571 struct request_queue *q;
567 struct block_device *bdev; 572 struct block_device *bdev;
568 struct list_head *head = &fs_devices->devices; 573 struct list_head *head = &fs_devices->devices;
569 struct btrfs_device *device; 574 struct btrfs_device *device;
@@ -620,6 +625,12 @@ static int __btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
620 seeding = 0; 625 seeding = 0;
621 } 626 }
622 627
628 q = bdev_get_queue(bdev);
629 if (blk_queue_discard(q)) {
630 device->can_discard = 1;
631 fs_devices->num_can_discard++;
632 }
633
623 device->bdev = bdev; 634 device->bdev = bdev;
624 device->in_fs_metadata = 0; 635 device->in_fs_metadata = 0;
625 device->mode = flags; 636 device->mode = flags;
@@ -1560,6 +1571,7 @@ error:
1560 1571
1561int btrfs_init_new_device(struct btrfs_root *root, char *device_path) 1572int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
1562{ 1573{
1574 struct request_queue *q;
1563 struct btrfs_trans_handle *trans; 1575 struct btrfs_trans_handle *trans;
1564 struct btrfs_device *device; 1576 struct btrfs_device *device;
1565 struct block_device *bdev; 1577 struct block_device *bdev;
@@ -1629,6 +1641,9 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
1629 1641
1630 lock_chunks(root); 1642 lock_chunks(root);
1631 1643
1644 q = bdev_get_queue(bdev);
1645 if (blk_queue_discard(q))
1646 device->can_discard = 1;
1632 device->writeable = 1; 1647 device->writeable = 1;
1633 device->work.func = pending_bios_fn; 1648 device->work.func = pending_bios_fn;
1634 generate_random_uuid(device->uuid); 1649 generate_random_uuid(device->uuid);
@@ -1664,6 +1679,8 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
1664 root->fs_info->fs_devices->num_devices++; 1679 root->fs_info->fs_devices->num_devices++;
1665 root->fs_info->fs_devices->open_devices++; 1680 root->fs_info->fs_devices->open_devices++;
1666 root->fs_info->fs_devices->rw_devices++; 1681 root->fs_info->fs_devices->rw_devices++;
1682 if (device->can_discard)
1683 root->fs_info->fs_devices->num_can_discard++;
1667 root->fs_info->fs_devices->total_rw_bytes += device->total_bytes; 1684 root->fs_info->fs_devices->total_rw_bytes += device->total_bytes;
1668 1685
1669 if (!blk_queue_nonrot(bdev_get_queue(bdev))) 1686 if (!blk_queue_nonrot(bdev_get_queue(bdev)))