diff options
author | Chris Ball <cjb@laptop.org> | 2009-04-27 07:29:03 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2009-04-27 07:40:51 -0400 |
commit | d6397baee468809ef311e763dfc6e9f73418f8a6 (patch) | |
tree | b8f20c01239674eea287c1665fbf96fb92dfcb00 /fs | |
parent | 59bc5c758ece00fb0b2a170dd8fbbf31f1856c8a (diff) |
Btrfs: When shrinking, only update disk size on success
Previously, we updated a device's size prior to attempting a shrink
operation. This patch moves the device resizing logic to only happen if
the shrink completes successfully. In the process, it introduces a new
field to btrfs_device -- disk_total_bytes -- to track the on-disk size.
Signed-off-by: Chris Ball <cjb@laptop.org>
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/volumes.c | 35 | ||||
-rw-r--r-- | fs/btrfs/volumes.h | 3 |
2 files changed, 27 insertions, 11 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index e53835b88594..5f01dad4b696 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -1543,7 +1543,7 @@ static noinline int btrfs_update_device(struct btrfs_trans_handle *trans, | |||
1543 | btrfs_set_device_io_align(leaf, dev_item, device->io_align); | 1543 | btrfs_set_device_io_align(leaf, dev_item, device->io_align); |
1544 | btrfs_set_device_io_width(leaf, dev_item, device->io_width); | 1544 | btrfs_set_device_io_width(leaf, dev_item, device->io_width); |
1545 | btrfs_set_device_sector_size(leaf, dev_item, device->sector_size); | 1545 | btrfs_set_device_sector_size(leaf, dev_item, device->sector_size); |
1546 | btrfs_set_device_total_bytes(leaf, dev_item, device->total_bytes); | 1546 | btrfs_set_device_total_bytes(leaf, dev_item, device->disk_total_bytes); |
1547 | btrfs_set_device_bytes_used(leaf, dev_item, device->bytes_used); | 1547 | btrfs_set_device_bytes_used(leaf, dev_item, device->bytes_used); |
1548 | btrfs_mark_buffer_dirty(leaf); | 1548 | btrfs_mark_buffer_dirty(leaf); |
1549 | 1549 | ||
@@ -1940,14 +1940,6 @@ int btrfs_shrink_device(struct btrfs_device *device, u64 new_size) | |||
1940 | device->total_bytes = new_size; | 1940 | device->total_bytes = new_size; |
1941 | if (device->writeable) | 1941 | if (device->writeable) |
1942 | device->fs_devices->total_rw_bytes -= diff; | 1942 | device->fs_devices->total_rw_bytes -= diff; |
1943 | ret = btrfs_update_device(trans, device); | ||
1944 | if (ret) { | ||
1945 | unlock_chunks(root); | ||
1946 | btrfs_end_transaction(trans, root); | ||
1947 | goto done; | ||
1948 | } | ||
1949 | WARN_ON(diff > old_total); | ||
1950 | btrfs_set_super_total_bytes(super_copy, old_total - diff); | ||
1951 | unlock_chunks(root); | 1943 | unlock_chunks(root); |
1952 | btrfs_end_transaction(trans, root); | 1944 | btrfs_end_transaction(trans, root); |
1953 | 1945 | ||
@@ -1979,7 +1971,7 @@ int btrfs_shrink_device(struct btrfs_device *device, u64 new_size) | |||
1979 | length = btrfs_dev_extent_length(l, dev_extent); | 1971 | length = btrfs_dev_extent_length(l, dev_extent); |
1980 | 1972 | ||
1981 | if (key.offset + length <= new_size) | 1973 | if (key.offset + length <= new_size) |
1982 | goto done; | 1974 | break; |
1983 | 1975 | ||
1984 | chunk_tree = btrfs_dev_extent_chunk_tree(l, dev_extent); | 1976 | chunk_tree = btrfs_dev_extent_chunk_tree(l, dev_extent); |
1985 | chunk_objectid = btrfs_dev_extent_chunk_objectid(l, dev_extent); | 1977 | chunk_objectid = btrfs_dev_extent_chunk_objectid(l, dev_extent); |
@@ -1992,6 +1984,26 @@ int btrfs_shrink_device(struct btrfs_device *device, u64 new_size) | |||
1992 | goto done; | 1984 | goto done; |
1993 | } | 1985 | } |
1994 | 1986 | ||
1987 | /* Shrinking succeeded, else we would be at "done". */ | ||
1988 | trans = btrfs_start_transaction(root, 1); | ||
1989 | if (!trans) { | ||
1990 | ret = -ENOMEM; | ||
1991 | goto done; | ||
1992 | } | ||
1993 | lock_chunks(root); | ||
1994 | |||
1995 | device->disk_total_bytes = new_size; | ||
1996 | /* Now btrfs_update_device() will change the on-disk size. */ | ||
1997 | ret = btrfs_update_device(trans, device); | ||
1998 | if (ret) { | ||
1999 | unlock_chunks(root); | ||
2000 | btrfs_end_transaction(trans, root); | ||
2001 | goto done; | ||
2002 | } | ||
2003 | WARN_ON(diff > old_total); | ||
2004 | btrfs_set_super_total_bytes(super_copy, old_total - diff); | ||
2005 | unlock_chunks(root); | ||
2006 | btrfs_end_transaction(trans, root); | ||
1995 | done: | 2007 | done: |
1996 | btrfs_free_path(path); | 2008 | btrfs_free_path(path); |
1997 | return ret; | 2009 | return ret; |
@@ -3076,7 +3088,8 @@ static int fill_device_from_item(struct extent_buffer *leaf, | |||
3076 | unsigned long ptr; | 3088 | unsigned long ptr; |
3077 | 3089 | ||
3078 | device->devid = btrfs_device_id(leaf, dev_item); | 3090 | device->devid = btrfs_device_id(leaf, dev_item); |
3079 | device->total_bytes = btrfs_device_total_bytes(leaf, dev_item); | 3091 | device->disk_total_bytes = btrfs_device_total_bytes(leaf, dev_item); |
3092 | device->total_bytes = device->disk_total_bytes; | ||
3080 | device->bytes_used = btrfs_device_bytes_used(leaf, dev_item); | 3093 | device->bytes_used = btrfs_device_bytes_used(leaf, dev_item); |
3081 | device->type = btrfs_device_type(leaf, dev_item); | 3094 | device->type = btrfs_device_type(leaf, dev_item); |
3082 | device->io_align = btrfs_device_io_align(leaf, dev_item); | 3095 | device->io_align = btrfs_device_io_align(leaf, dev_item); |
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index 5836327ba5dd..5c3ff6d02fd7 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h | |||
@@ -61,6 +61,9 @@ struct btrfs_device { | |||
61 | /* size of the device */ | 61 | /* size of the device */ |
62 | u64 total_bytes; | 62 | u64 total_bytes; |
63 | 63 | ||
64 | /* size of the disk */ | ||
65 | u64 disk_total_bytes; | ||
66 | |||
64 | /* bytes used */ | 67 | /* bytes used */ |
65 | u64 bytes_used; | 68 | u64 bytes_used; |
66 | 69 | ||