diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2011-08-19 10:31:36 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-08-19 10:31:36 -0700 |
commit | d51f2c3010997fc36384496eca4f79fe8e63af3e (patch) | |
tree | b957a09b36a8d428930b9c622edd03cefdcd3594 | |
parent | 947bd36fdaa2b980949a83579f04076b7e90dc6a (diff) | |
download | stable-queue-d51f2c3010997fc36384496eca4f79fe8e63af3e.tar.gz |
3.0 patches
-rw-r--r-- | queue-3.0/btrfs-detect-wether-a-device-supports-discard.patch | 145 | ||||
-rw-r--r-- | queue-3.0/series | 1 |
2 files changed, 146 insertions, 0 deletions
diff --git a/queue-3.0/btrfs-detect-wether-a-device-supports-discard.patch b/queue-3.0/btrfs-detect-wether-a-device-supports-discard.patch new file mode 100644 index 0000000000..95d5ed0fb3 --- /dev/null +++ b/queue-3.0/btrfs-detect-wether-a-device-supports-discard.patch @@ -0,0 +1,145 @@ +From d5e2003c2bcda93a8f2e668eb4642d70c9c38301 Mon Sep 17 00:00:00 2001 +From: Josef Bacik <josef@redhat.com> +Date: Thu, 4 Aug 2011 14:52:27 +0000 +Subject: Btrfs: detect wether a device supports discard + +From: Josef Bacik <josef@redhat.com> + +commit d5e2003c2bcda93a8f2e668eb4642d70c9c38301 upstream. + +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> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + fs/btrfs/extent-tree.c | 12 ++++++++++-- + fs/btrfs/volumes.c | 17 +++++++++++++++++ + fs/btrfs/volumes.h | 2 ++ + 3 files changed, 29 insertions(+), 2 deletions(-) + +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -1784,6 +1784,9 @@ static int btrfs_discard_extent(struct b + + + for (i = 0; i < multi->num_stripes; i++, stripe++) { ++ if (!stripe->dev->can_discard) ++ continue; ++ + ret = btrfs_issue_discard(stripe->dev->bdev, + stripe->physical, + stripe->length); +@@ -1791,11 +1794,16 @@ static int btrfs_discard_extent(struct b + discarded_bytes += stripe->length; + else if (ret != -EOPNOTSUPP) + break; ++ ++ /* ++ * Just in case we get back EOPNOTSUPP for some reason, ++ * just ignore the return value so we don't screw up ++ * people calling discard_extent. ++ */ ++ ret = 0; + } + kfree(multi); + } +- if (discarded_bytes && ret == -EOPNOTSUPP) +- ret = 0; + + if (actual_bytes) + *actual_bytes = discarded_bytes; +--- a/fs/btrfs/volumes.c ++++ b/fs/btrfs/volumes.c +@@ -500,6 +500,9 @@ static int __btrfs_close_devices(struct + fs_devices->rw_devices--; + } + ++ if (device->can_discard) ++ fs_devices->num_can_discard--; ++ + new_device = kmalloc(sizeof(*new_device), GFP_NOFS); + BUG_ON(!new_device); + memcpy(new_device, device, sizeof(*new_device)); +@@ -508,6 +511,7 @@ static int __btrfs_close_devices(struct + new_device->bdev = NULL; + new_device->writeable = 0; + new_device->in_fs_metadata = 0; ++ new_device->can_discard = 0; + list_replace_rcu(&device->dev_list, &new_device->dev_list); + + call_rcu(&device->rcu, free_device); +@@ -547,6 +551,7 @@ int btrfs_close_devices(struct btrfs_fs_ + static int __btrfs_open_devices(struct btrfs_fs_devices *fs_devices, + fmode_t flags, void *holder) + { ++ struct request_queue *q; + struct block_device *bdev; + struct list_head *head = &fs_devices->devices; + struct btrfs_device *device; +@@ -603,6 +608,12 @@ static int __btrfs_open_devices(struct b + seeding = 0; + } + ++ q = bdev_get_queue(bdev); ++ if (blk_queue_discard(q)) { ++ device->can_discard = 1; ++ fs_devices->num_can_discard++; ++ } ++ + device->bdev = bdev; + device->in_fs_metadata = 0; + device->mode = flags; +@@ -1542,6 +1553,7 @@ error: + + int btrfs_init_new_device(struct btrfs_root *root, char *device_path) + { ++ struct request_queue *q; + struct btrfs_trans_handle *trans; + struct btrfs_device *device; + struct block_device *bdev; +@@ -1611,6 +1623,9 @@ int btrfs_init_new_device(struct btrfs_r + + lock_chunks(root); + ++ q = bdev_get_queue(bdev); ++ if (blk_queue_discard(q)) ++ device->can_discard = 1; + device->writeable = 1; + device->work.func = pending_bios_fn; + generate_random_uuid(device->uuid); +@@ -1646,6 +1661,8 @@ int btrfs_init_new_device(struct btrfs_r + root->fs_info->fs_devices->num_devices++; + root->fs_info->fs_devices->open_devices++; + root->fs_info->fs_devices->rw_devices++; ++ if (device->can_discard) ++ root->fs_info->fs_devices->num_can_discard++; + root->fs_info->fs_devices->total_rw_bytes += device->total_bytes; + + if (!blk_queue_nonrot(bdev_get_queue(bdev))) +--- a/fs/btrfs/volumes.h ++++ b/fs/btrfs/volumes.h +@@ -48,6 +48,7 @@ struct btrfs_device { + int writeable; + int in_fs_metadata; + int missing; ++ int can_discard; + + spinlock_t io_lock; + +@@ -104,6 +105,7 @@ struct btrfs_fs_devices { + u64 rw_devices; + u64 missing_devices; + u64 total_rw_bytes; ++ u64 num_can_discard; + struct block_device *latest_bdev; + + /* all of the devices in the FS, protected by a mutex diff --git a/queue-3.0/series b/queue-3.0/series index 07bb57d881..c473522f40 100644 --- a/queue-3.0/series +++ b/queue-3.0/series @@ -10,3 +10,4 @@ pnfs-obj-bug-when-we-are-running-out-of-bio.patch nfsv4.1-fix-the-callback-highest_used_slotid-behaviour.patch nfsv4.1-return-nfs4err_badsession-to-callbacks-during.patch x86-mtrr-lock-stop-machine-during-mtrr-rendezvous-sequence.patch +btrfs-detect-wether-a-device-supports-discard.patch |