diff options
-rw-r--r-- | fs/btrfs/ctree.h | 3 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 101 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 139 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 27 | ||||
-rw-r--r-- | fs/btrfs/super.c | 35 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 5 | ||||
-rw-r--r-- | fs/btrfs/volumes.c | 221 | ||||
-rw-r--r-- | fs/btrfs/volumes.h | 3 |
8 files changed, 412 insertions, 122 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 3b6f8524a4ad..33ab165591c5 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -505,7 +505,7 @@ struct btrfs_fs_info { | |||
505 | u64 alloc_start; | 505 | u64 alloc_start; |
506 | struct btrfs_transaction *running_transaction; | 506 | struct btrfs_transaction *running_transaction; |
507 | struct btrfs_super_block super_copy; | 507 | struct btrfs_super_block super_copy; |
508 | struct extent_buffer *sb_buffer; | 508 | struct btrfs_super_block super_for_commit; |
509 | struct block_device *__bdev; | 509 | struct block_device *__bdev; |
510 | struct super_block *sb; | 510 | struct super_block *sb; |
511 | struct inode *btree_inode; | 511 | struct inode *btree_inode; |
@@ -1208,6 +1208,7 @@ BTRFS_SETGET_STACK_FUNCS(root_limit, struct btrfs_root_item, byte_limit, 64); | |||
1208 | 1208 | ||
1209 | /* struct btrfs_super_block */ | 1209 | /* struct btrfs_super_block */ |
1210 | BTRFS_SETGET_STACK_FUNCS(super_bytenr, struct btrfs_super_block, bytenr, 64); | 1210 | BTRFS_SETGET_STACK_FUNCS(super_bytenr, struct btrfs_super_block, bytenr, 64); |
1211 | BTRFS_SETGET_STACK_FUNCS(super_flags, struct btrfs_super_block, flags, 64); | ||
1211 | BTRFS_SETGET_STACK_FUNCS(super_generation, struct btrfs_super_block, | 1212 | BTRFS_SETGET_STACK_FUNCS(super_generation, struct btrfs_super_block, |
1212 | generation, 64); | 1213 | generation, 64); |
1213 | BTRFS_SETGET_STACK_FUNCS(super_root, struct btrfs_super_block, root, 64); | 1214 | BTRFS_SETGET_STACK_FUNCS(super_root, struct btrfs_super_block, root, 64); |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index fabc31b334b6..9d5424ad01a3 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -78,9 +78,13 @@ struct extent_map *btree_get_extent(struct inode *inode, struct page *page, | |||
78 | 78 | ||
79 | spin_lock(&em_tree->lock); | 79 | spin_lock(&em_tree->lock); |
80 | em = lookup_extent_mapping(em_tree, start, len); | 80 | em = lookup_extent_mapping(em_tree, start, len); |
81 | spin_unlock(&em_tree->lock); | 81 | if (em) { |
82 | if (em) | 82 | em->bdev = |
83 | BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev; | ||
84 | spin_unlock(&em_tree->lock); | ||
83 | goto out; | 85 | goto out; |
86 | } | ||
87 | spin_unlock(&em_tree->lock); | ||
84 | 88 | ||
85 | em = alloc_extent_map(GFP_NOFS); | 89 | em = alloc_extent_map(GFP_NOFS); |
86 | if (!em) { | 90 | if (!em) { |
@@ -90,7 +94,7 @@ struct extent_map *btree_get_extent(struct inode *inode, struct page *page, | |||
90 | em->start = 0; | 94 | em->start = 0; |
91 | em->len = (u64)-1; | 95 | em->len = (u64)-1; |
92 | em->block_start = 0; | 96 | em->block_start = 0; |
93 | em->bdev = inode->i_sb->s_bdev; | 97 | em->bdev = BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev; |
94 | 98 | ||
95 | spin_lock(&em_tree->lock); | 99 | spin_lock(&em_tree->lock); |
96 | ret = add_extent_mapping(em_tree, em); | 100 | ret = add_extent_mapping(em_tree, em); |
@@ -435,11 +439,6 @@ static int __btree_submit_bio_hook(struct inode *inode, int rw, struct bio *bio, | |||
435 | ret = btrfs_bio_wq_end_io(root->fs_info, bio, 1); | 439 | ret = btrfs_bio_wq_end_io(root->fs_info, bio, 1); |
436 | BUG_ON(ret); | 440 | BUG_ON(ret); |
437 | 441 | ||
438 | if (offset == BTRFS_SUPER_INFO_OFFSET) { | ||
439 | bio->bi_bdev = root->fs_info->fs_devices->latest_bdev; | ||
440 | submit_bio(rw, bio); | ||
441 | return 0; | ||
442 | } | ||
443 | return btrfs_map_bio(BTRFS_I(inode)->root, rw, bio, mirror_num); | 442 | return btrfs_map_bio(BTRFS_I(inode)->root, rw, bio, mirror_num); |
444 | } | 443 | } |
445 | 444 | ||
@@ -587,8 +586,7 @@ static int close_all_devices(struct btrfs_fs_info *fs_info) | |||
587 | list = &fs_info->fs_devices->devices; | 586 | list = &fs_info->fs_devices->devices; |
588 | list_for_each(next, list) { | 587 | list_for_each(next, list) { |
589 | device = list_entry(next, struct btrfs_device, dev_list); | 588 | device = list_entry(next, struct btrfs_device, dev_list); |
590 | if (device->bdev && device->bdev != fs_info->sb->s_bdev) | 589 | close_bdev_excl(device->bdev); |
591 | close_bdev_excl(device->bdev); | ||
592 | device->bdev = NULL; | 590 | device->bdev = NULL; |
593 | } | 591 | } |
594 | return 0; | 592 | return 0; |
@@ -1118,6 +1116,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1118 | u32 leafsize; | 1116 | u32 leafsize; |
1119 | u32 blocksize; | 1117 | u32 blocksize; |
1120 | u32 stripesize; | 1118 | u32 stripesize; |
1119 | struct buffer_head *bh; | ||
1121 | struct btrfs_root *extent_root = kmalloc(sizeof(struct btrfs_root), | 1120 | struct btrfs_root *extent_root = kmalloc(sizeof(struct btrfs_root), |
1122 | GFP_NOFS); | 1121 | GFP_NOFS); |
1123 | struct btrfs_root *tree_root = kmalloc(sizeof(struct btrfs_root), | 1122 | struct btrfs_root *tree_root = kmalloc(sizeof(struct btrfs_root), |
@@ -1153,7 +1152,6 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1153 | spin_lock_init(&fs_info->new_trans_lock); | 1152 | spin_lock_init(&fs_info->new_trans_lock); |
1154 | 1153 | ||
1155 | init_completion(&fs_info->kobj_unregister); | 1154 | init_completion(&fs_info->kobj_unregister); |
1156 | sb_set_blocksize(sb, BTRFS_SUPER_INFO_SIZE); | ||
1157 | fs_info->tree_root = tree_root; | 1155 | fs_info->tree_root = tree_root; |
1158 | fs_info->extent_root = extent_root; | 1156 | fs_info->extent_root = extent_root; |
1159 | fs_info->chunk_root = chunk_root; | 1157 | fs_info->chunk_root = chunk_root; |
@@ -1170,6 +1168,9 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1170 | fs_info->btree_inode->i_ino = 1; | 1168 | fs_info->btree_inode->i_ino = 1; |
1171 | fs_info->btree_inode->i_nlink = 1; | 1169 | fs_info->btree_inode->i_nlink = 1; |
1172 | 1170 | ||
1171 | sb->s_blocksize = 4096; | ||
1172 | sb->s_blocksize_bits = blksize_bits(4096); | ||
1173 | |||
1173 | /* | 1174 | /* |
1174 | * we set the i_size on the btree inode to the max possible int. | 1175 | * we set the i_size on the btree inode to the max possible int. |
1175 | * the real end of the address space is determined by all of | 1176 | * the real end of the address space is determined by all of |
@@ -1229,19 +1230,16 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1229 | __setup_root(4096, 4096, 4096, 4096, tree_root, | 1230 | __setup_root(4096, 4096, 4096, 4096, tree_root, |
1230 | fs_info, BTRFS_ROOT_TREE_OBJECTID); | 1231 | fs_info, BTRFS_ROOT_TREE_OBJECTID); |
1231 | 1232 | ||
1232 | fs_info->sb_buffer = read_tree_block(tree_root, | ||
1233 | BTRFS_SUPER_INFO_OFFSET, | ||
1234 | 4096); | ||
1235 | 1233 | ||
1236 | if (!fs_info->sb_buffer) | 1234 | bh = __bread(fs_devices->latest_bdev, |
1235 | BTRFS_SUPER_INFO_OFFSET / 4096, 4096); | ||
1236 | if (!bh) | ||
1237 | goto fail_iput; | 1237 | goto fail_iput; |
1238 | 1238 | ||
1239 | read_extent_buffer(fs_info->sb_buffer, &fs_info->super_copy, 0, | 1239 | memcpy(&fs_info->super_copy, bh->b_data, sizeof(fs_info->super_copy)); |
1240 | sizeof(fs_info->super_copy)); | 1240 | brelse(bh); |
1241 | 1241 | ||
1242 | read_extent_buffer(fs_info->sb_buffer, fs_info->fsid, | 1242 | memcpy(fs_info->fsid, fs_info->super_copy.fsid, BTRFS_FSID_SIZE); |
1243 | (unsigned long)btrfs_super_fsid(fs_info->sb_buffer), | ||
1244 | BTRFS_FSID_SIZE); | ||
1245 | 1243 | ||
1246 | disk_super = &fs_info->super_copy; | 1244 | disk_super = &fs_info->super_copy; |
1247 | if (!btrfs_super_root(disk_super)) | 1245 | if (!btrfs_super_root(disk_super)) |
@@ -1263,7 +1261,9 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1263 | tree_root->leafsize = leafsize; | 1261 | tree_root->leafsize = leafsize; |
1264 | tree_root->sectorsize = sectorsize; | 1262 | tree_root->sectorsize = sectorsize; |
1265 | tree_root->stripesize = stripesize; | 1263 | tree_root->stripesize = stripesize; |
1266 | sb_set_blocksize(sb, sectorsize); | 1264 | |
1265 | sb->s_blocksize = sectorsize; | ||
1266 | sb->s_blocksize_bits = blksize_bits(sectorsize); | ||
1267 | 1267 | ||
1268 | if (strncmp((char *)(&disk_super->magic), BTRFS_MAGIC, | 1268 | if (strncmp((char *)(&disk_super->magic), BTRFS_MAGIC, |
1269 | sizeof(disk_super->magic))) { | 1269 | sizeof(disk_super->magic))) { |
@@ -1339,7 +1339,6 @@ fail_tree_root: | |||
1339 | fail_sys_array: | 1339 | fail_sys_array: |
1340 | mutex_unlock(&fs_info->fs_mutex); | 1340 | mutex_unlock(&fs_info->fs_mutex); |
1341 | fail_sb_buffer: | 1341 | fail_sb_buffer: |
1342 | free_extent_buffer(fs_info->sb_buffer); | ||
1343 | extent_io_tree_empty_lru(&BTRFS_I(fs_info->btree_inode)->io_tree); | 1342 | extent_io_tree_empty_lru(&BTRFS_I(fs_info->btree_inode)->io_tree); |
1344 | fail_iput: | 1343 | fail_iput: |
1345 | iput(fs_info->btree_inode); | 1344 | iput(fs_info->btree_inode); |
@@ -1380,41 +1379,44 @@ int write_all_supers(struct btrfs_root *root) | |||
1380 | struct list_head *cur; | 1379 | struct list_head *cur; |
1381 | struct list_head *head = &root->fs_info->fs_devices->devices; | 1380 | struct list_head *head = &root->fs_info->fs_devices->devices; |
1382 | struct btrfs_device *dev; | 1381 | struct btrfs_device *dev; |
1383 | struct extent_buffer *sb; | 1382 | struct btrfs_super_block *sb; |
1384 | struct btrfs_dev_item *dev_item; | 1383 | struct btrfs_dev_item *dev_item; |
1385 | struct buffer_head *bh; | 1384 | struct buffer_head *bh; |
1386 | int ret; | 1385 | int ret; |
1387 | int do_barriers; | 1386 | int do_barriers; |
1388 | int max_errors; | 1387 | int max_errors; |
1389 | int total_errors = 0; | 1388 | int total_errors = 0; |
1389 | u32 crc; | ||
1390 | u64 flags; | ||
1390 | 1391 | ||
1391 | max_errors = btrfs_super_num_devices(&root->fs_info->super_copy) - 1; | 1392 | max_errors = btrfs_super_num_devices(&root->fs_info->super_copy) - 1; |
1392 | do_barriers = !btrfs_test_opt(root, NOBARRIER); | 1393 | do_barriers = !btrfs_test_opt(root, NOBARRIER); |
1393 | 1394 | ||
1394 | sb = root->fs_info->sb_buffer; | 1395 | sb = &root->fs_info->super_for_commit; |
1395 | dev_item = (struct btrfs_dev_item *)offsetof(struct btrfs_super_block, | 1396 | dev_item = &sb->dev_item; |
1396 | dev_item); | ||
1397 | list_for_each(cur, head) { | 1397 | list_for_each(cur, head) { |
1398 | dev = list_entry(cur, struct btrfs_device, dev_list); | 1398 | dev = list_entry(cur, struct btrfs_device, dev_list); |
1399 | btrfs_set_device_type(sb, dev_item, dev->type); | 1399 | btrfs_set_stack_device_type(dev_item, dev->type); |
1400 | btrfs_set_device_id(sb, dev_item, dev->devid); | 1400 | btrfs_set_stack_device_id(dev_item, dev->devid); |
1401 | btrfs_set_device_total_bytes(sb, dev_item, dev->total_bytes); | 1401 | btrfs_set_stack_device_total_bytes(dev_item, dev->total_bytes); |
1402 | btrfs_set_device_bytes_used(sb, dev_item, dev->bytes_used); | 1402 | btrfs_set_stack_device_bytes_used(dev_item, dev->bytes_used); |
1403 | btrfs_set_device_io_align(sb, dev_item, dev->io_align); | 1403 | btrfs_set_stack_device_io_align(dev_item, dev->io_align); |
1404 | btrfs_set_device_io_width(sb, dev_item, dev->io_width); | 1404 | btrfs_set_stack_device_io_width(dev_item, dev->io_width); |
1405 | btrfs_set_device_sector_size(sb, dev_item, dev->sector_size); | 1405 | btrfs_set_stack_device_sector_size(dev_item, dev->sector_size); |
1406 | write_extent_buffer(sb, dev->uuid, | 1406 | memcpy(dev_item->uuid, dev->uuid, BTRFS_UUID_SIZE); |
1407 | (unsigned long)btrfs_device_uuid(dev_item), | 1407 | flags = btrfs_super_flags(sb); |
1408 | BTRFS_UUID_SIZE); | 1408 | btrfs_set_super_flags(sb, flags | BTRFS_HEADER_FLAG_WRITTEN); |
1409 | 1409 | ||
1410 | btrfs_set_header_flag(sb, BTRFS_HEADER_FLAG_WRITTEN); | 1410 | |
1411 | csum_tree_block(root, sb, 0); | 1411 | crc = ~(u32)0; |
1412 | 1412 | crc = btrfs_csum_data(root, (char *)sb + BTRFS_CSUM_SIZE, crc, | |
1413 | bh = __getblk(dev->bdev, BTRFS_SUPER_INFO_OFFSET / | 1413 | BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE); |
1414 | root->fs_info->sb->s_blocksize, | 1414 | btrfs_csum_final(crc, sb->csum); |
1415 | |||
1416 | bh = __getblk(dev->bdev, BTRFS_SUPER_INFO_OFFSET / 4096, | ||
1415 | BTRFS_SUPER_INFO_SIZE); | 1417 | BTRFS_SUPER_INFO_SIZE); |
1416 | 1418 | ||
1417 | read_extent_buffer(sb, bh->b_data, 0, BTRFS_SUPER_INFO_SIZE); | 1419 | memcpy(bh->b_data, sb, BTRFS_SUPER_INFO_SIZE); |
1418 | dev->pending_io = bh; | 1420 | dev->pending_io = bh; |
1419 | 1421 | ||
1420 | get_bh(bh); | 1422 | get_bh(bh); |
@@ -1483,15 +1485,6 @@ int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1483 | int ret; | 1485 | int ret; |
1484 | 1486 | ||
1485 | ret = write_all_supers(root); | 1487 | ret = write_all_supers(root); |
1486 | #if 0 | ||
1487 | if (!btrfs_test_opt(root, NOBARRIER)) | ||
1488 | blkdev_issue_flush(sb->s_bdev, NULL); | ||
1489 | set_extent_buffer_dirty(&BTRFS_I(btree_inode)->io_tree, super); | ||
1490 | ret = sync_page_range_nolock(btree_inode, btree_inode->i_mapping, | ||
1491 | super->start, super->len); | ||
1492 | if (!btrfs_test_opt(root, NOBARRIER)) | ||
1493 | blkdev_issue_flush(sb->s_bdev, NULL); | ||
1494 | #endif | ||
1495 | return ret; | 1488 | return ret; |
1496 | } | 1489 | } |
1497 | 1490 | ||
@@ -1570,8 +1563,6 @@ int close_ctree(struct btrfs_root *root) | |||
1570 | if (root->fs_info->dev_root->node); | 1563 | if (root->fs_info->dev_root->node); |
1571 | free_extent_buffer(root->fs_info->dev_root->node); | 1564 | free_extent_buffer(root->fs_info->dev_root->node); |
1572 | 1565 | ||
1573 | free_extent_buffer(fs_info->sb_buffer); | ||
1574 | |||
1575 | btrfs_free_block_groups(root->fs_info); | 1566 | btrfs_free_block_groups(root->fs_info); |
1576 | del_fs_roots(fs_info); | 1567 | del_fs_roots(fs_info); |
1577 | 1568 | ||
@@ -1652,7 +1643,7 @@ void btrfs_throttle(struct btrfs_root *root) | |||
1652 | { | 1643 | { |
1653 | struct backing_dev_info *bdi; | 1644 | struct backing_dev_info *bdi; |
1654 | 1645 | ||
1655 | bdi = root->fs_info->sb->s_bdev->bd_inode->i_mapping->backing_dev_info; | 1646 | bdi = &root->fs_info->bdi; |
1656 | if (root->fs_info->throttles && bdi_write_congested(bdi)) { | 1647 | if (root->fs_info->throttles && bdi_write_congested(bdi)) { |
1657 | #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18) | 1648 | #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18) |
1658 | congestion_wait(WRITE, HZ/20); | 1649 | congestion_wait(WRITE, HZ/20); |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index f94794a99329..c0e67bde8428 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -147,6 +147,8 @@ struct btrfs_block_group_cache *btrfs_lookup_block_group(struct | |||
147 | u64 end; | 147 | u64 end; |
148 | int ret; | 148 | int ret; |
149 | 149 | ||
150 | bytenr = max_t(u64, bytenr, | ||
151 | BTRFS_SUPER_INFO_OFFSET + BTRFS_SUPER_INFO_SIZE); | ||
150 | block_group_cache = &info->block_group_cache; | 152 | block_group_cache = &info->block_group_cache; |
151 | ret = find_first_extent_bit(block_group_cache, | 153 | ret = find_first_extent_bit(block_group_cache, |
152 | bytenr, &start, &end, | 154 | bytenr, &start, &end, |
@@ -1059,16 +1061,25 @@ static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags) | |||
1059 | } | 1061 | } |
1060 | } | 1062 | } |
1061 | 1063 | ||
1062 | static u64 reduce_alloc_profile(u64 flags) | 1064 | static u64 reduce_alloc_profile(struct btrfs_root *root, u64 flags) |
1063 | { | 1065 | { |
1066 | u64 num_devices = root->fs_info->fs_devices->num_devices; | ||
1067 | |||
1068 | if (num_devices == 1) | ||
1069 | flags &= ~(BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID0); | ||
1070 | if (num_devices < 4) | ||
1071 | flags &= ~BTRFS_BLOCK_GROUP_RAID10; | ||
1072 | |||
1064 | if ((flags & BTRFS_BLOCK_GROUP_DUP) && | 1073 | if ((flags & BTRFS_BLOCK_GROUP_DUP) && |
1065 | (flags & (BTRFS_BLOCK_GROUP_RAID1 | | 1074 | (flags & (BTRFS_BLOCK_GROUP_RAID1 | |
1066 | BTRFS_BLOCK_GROUP_RAID10))) | 1075 | BTRFS_BLOCK_GROUP_RAID10))) { |
1067 | flags &= ~BTRFS_BLOCK_GROUP_DUP; | 1076 | flags &= ~BTRFS_BLOCK_GROUP_DUP; |
1077 | } | ||
1068 | 1078 | ||
1069 | if ((flags & BTRFS_BLOCK_GROUP_RAID1) && | 1079 | if ((flags & BTRFS_BLOCK_GROUP_RAID1) && |
1070 | (flags & BTRFS_BLOCK_GROUP_RAID10)) | 1080 | (flags & BTRFS_BLOCK_GROUP_RAID10)) { |
1071 | flags &= ~BTRFS_BLOCK_GROUP_RAID1; | 1081 | flags &= ~BTRFS_BLOCK_GROUP_RAID1; |
1082 | } | ||
1072 | 1083 | ||
1073 | if ((flags & BTRFS_BLOCK_GROUP_RAID0) && | 1084 | if ((flags & BTRFS_BLOCK_GROUP_RAID0) && |
1074 | ((flags & BTRFS_BLOCK_GROUP_RAID1) | | 1085 | ((flags & BTRFS_BLOCK_GROUP_RAID1) | |
@@ -1078,7 +1089,6 @@ static u64 reduce_alloc_profile(u64 flags) | |||
1078 | return flags; | 1089 | return flags; |
1079 | } | 1090 | } |
1080 | 1091 | ||
1081 | |||
1082 | static int do_chunk_alloc(struct btrfs_trans_handle *trans, | 1092 | static int do_chunk_alloc(struct btrfs_trans_handle *trans, |
1083 | struct btrfs_root *extent_root, u64 alloc_bytes, | 1093 | struct btrfs_root *extent_root, u64 alloc_bytes, |
1084 | u64 flags) | 1094 | u64 flags) |
@@ -1089,7 +1099,7 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans, | |||
1089 | u64 num_bytes; | 1099 | u64 num_bytes; |
1090 | int ret; | 1100 | int ret; |
1091 | 1101 | ||
1092 | flags = reduce_alloc_profile(flags); | 1102 | flags = reduce_alloc_profile(extent_root, flags); |
1093 | 1103 | ||
1094 | space_info = __find_space_info(extent_root->fs_info, flags); | 1104 | space_info = __find_space_info(extent_root->fs_info, flags); |
1095 | if (!space_info) { | 1105 | if (!space_info) { |
@@ -1169,6 +1179,21 @@ static int update_block_group(struct btrfs_trans_handle *trans, | |||
1169 | return 0; | 1179 | return 0; |
1170 | } | 1180 | } |
1171 | 1181 | ||
1182 | static u64 first_logical_byte(struct btrfs_root *root, u64 search_start) | ||
1183 | { | ||
1184 | u64 start; | ||
1185 | u64 end; | ||
1186 | int ret; | ||
1187 | ret = find_first_extent_bit(&root->fs_info->block_group_cache, | ||
1188 | search_start, &start, &end, | ||
1189 | BLOCK_GROUP_DATA | BLOCK_GROUP_METADATA | | ||
1190 | BLOCK_GROUP_SYSTEM); | ||
1191 | if (ret) | ||
1192 | return 0; | ||
1193 | return start; | ||
1194 | } | ||
1195 | |||
1196 | |||
1172 | static int update_pinned_extents(struct btrfs_root *root, | 1197 | static int update_pinned_extents(struct btrfs_root *root, |
1173 | u64 bytenr, u64 num, int pin) | 1198 | u64 bytenr, u64 num, int pin) |
1174 | { | 1199 | { |
@@ -1185,16 +1210,25 @@ static int update_pinned_extents(struct btrfs_root *root, | |||
1185 | } | 1210 | } |
1186 | while (num > 0) { | 1211 | while (num > 0) { |
1187 | cache = btrfs_lookup_block_group(fs_info, bytenr); | 1212 | cache = btrfs_lookup_block_group(fs_info, bytenr); |
1188 | WARN_ON(!cache); | 1213 | if (!cache) { |
1189 | len = min(num, cache->key.offset - | 1214 | u64 first = first_logical_byte(root, bytenr); |
1190 | (bytenr - cache->key.objectid)); | 1215 | WARN_ON(first < bytenr); |
1216 | len = min(first - bytenr, num); | ||
1217 | } else { | ||
1218 | len = min(num, cache->key.offset - | ||
1219 | (bytenr - cache->key.objectid)); | ||
1220 | } | ||
1191 | if (pin) { | 1221 | if (pin) { |
1192 | cache->pinned += len; | 1222 | if (cache) { |
1193 | cache->space_info->bytes_pinned += len; | 1223 | cache->pinned += len; |
1224 | cache->space_info->bytes_pinned += len; | ||
1225 | } | ||
1194 | fs_info->total_pinned += len; | 1226 | fs_info->total_pinned += len; |
1195 | } else { | 1227 | } else { |
1196 | cache->pinned -= len; | 1228 | if (cache) { |
1197 | cache->space_info->bytes_pinned -= len; | 1229 | cache->pinned -= len; |
1230 | cache->space_info->bytes_pinned -= len; | ||
1231 | } | ||
1198 | fs_info->total_pinned -= len; | 1232 | fs_info->total_pinned -= len; |
1199 | } | 1233 | } |
1200 | bytenr += len; | 1234 | bytenr += len; |
@@ -1547,7 +1581,7 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans, | |||
1547 | int data) | 1581 | int data) |
1548 | { | 1582 | { |
1549 | int ret; | 1583 | int ret; |
1550 | u64 orig_search_start = search_start; | 1584 | u64 orig_search_start; |
1551 | struct btrfs_root * root = orig_root->fs_info->extent_root; | 1585 | struct btrfs_root * root = orig_root->fs_info->extent_root; |
1552 | struct btrfs_fs_info *info = root->fs_info; | 1586 | struct btrfs_fs_info *info = root->fs_info; |
1553 | u64 total_needed = num_bytes; | 1587 | u64 total_needed = num_bytes; |
@@ -1577,6 +1611,9 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans, | |||
1577 | } | 1611 | } |
1578 | } | 1612 | } |
1579 | 1613 | ||
1614 | search_start = max(search_start, first_logical_byte(root, 0)); | ||
1615 | orig_search_start = search_start; | ||
1616 | |||
1580 | if (search_end == (u64)-1) | 1617 | if (search_end == (u64)-1) |
1581 | search_end = btrfs_super_total_bytes(&info->super_copy); | 1618 | search_end = btrfs_super_total_bytes(&info->super_copy); |
1582 | 1619 | ||
@@ -1751,7 +1788,7 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, | |||
1751 | data = BTRFS_BLOCK_GROUP_METADATA | alloc_profile; | 1788 | data = BTRFS_BLOCK_GROUP_METADATA | alloc_profile; |
1752 | } | 1789 | } |
1753 | again: | 1790 | again: |
1754 | data = reduce_alloc_profile(data); | 1791 | data = reduce_alloc_profile(root, data); |
1755 | if (root->ref_cows) { | 1792 | if (root->ref_cows) { |
1756 | if (!(data & BTRFS_BLOCK_GROUP_METADATA)) { | 1793 | if (!(data & BTRFS_BLOCK_GROUP_METADATA)) { |
1757 | ret = do_chunk_alloc(trans, root->fs_info->extent_root, | 1794 | ret = do_chunk_alloc(trans, root->fs_info->extent_root, |
@@ -2309,6 +2346,7 @@ static int noinline relocate_inode_pages(struct inode *inode, u64 start, | |||
2309 | struct file_ra_state *ra; | 2346 | struct file_ra_state *ra; |
2310 | unsigned long total_read = 0; | 2347 | unsigned long total_read = 0; |
2311 | unsigned long ra_pages; | 2348 | unsigned long ra_pages; |
2349 | struct btrfs_trans_handle *trans; | ||
2312 | 2350 | ||
2313 | ra = kzalloc(sizeof(*ra), GFP_NOFS); | 2351 | ra = kzalloc(sizeof(*ra), GFP_NOFS); |
2314 | 2352 | ||
@@ -2326,9 +2364,13 @@ static int noinline relocate_inode_pages(struct inode *inode, u64 start, | |||
2326 | calc_ra(i, last_index, ra_pages)); | 2364 | calc_ra(i, last_index, ra_pages)); |
2327 | } | 2365 | } |
2328 | total_read++; | 2366 | total_read++; |
2367 | if (((u64)i << PAGE_CACHE_SHIFT) > inode->i_size) | ||
2368 | goto truncate_racing; | ||
2369 | |||
2329 | page = grab_cache_page(inode->i_mapping, i); | 2370 | page = grab_cache_page(inode->i_mapping, i); |
2330 | if (!page) | 2371 | if (!page) { |
2331 | goto out_unlock; | 2372 | goto out_unlock; |
2373 | } | ||
2332 | if (!PageUptodate(page)) { | 2374 | if (!PageUptodate(page)) { |
2333 | btrfs_readpage(NULL, page); | 2375 | btrfs_readpage(NULL, page); |
2334 | lock_page(page); | 2376 | lock_page(page); |
@@ -2350,20 +2392,33 @@ static int noinline relocate_inode_pages(struct inode *inode, u64 start, | |||
2350 | 2392 | ||
2351 | lock_extent(io_tree, page_start, page_end, GFP_NOFS); | 2393 | lock_extent(io_tree, page_start, page_end, GFP_NOFS); |
2352 | 2394 | ||
2353 | set_page_dirty(page); | ||
2354 | set_extent_delalloc(io_tree, page_start, | 2395 | set_extent_delalloc(io_tree, page_start, |
2355 | page_end, GFP_NOFS); | 2396 | page_end, GFP_NOFS); |
2397 | set_page_dirty(page); | ||
2356 | 2398 | ||
2357 | unlock_extent(io_tree, page_start, page_end, GFP_NOFS); | 2399 | unlock_extent(io_tree, page_start, page_end, GFP_NOFS); |
2358 | unlock_page(page); | 2400 | unlock_page(page); |
2359 | page_cache_release(page); | 2401 | page_cache_release(page); |
2360 | balance_dirty_pages_ratelimited_nr(inode->i_mapping, 1); | ||
2361 | } | 2402 | } |
2403 | balance_dirty_pages_ratelimited_nr(inode->i_mapping, | ||
2404 | total_read); | ||
2362 | 2405 | ||
2363 | out_unlock: | 2406 | out_unlock: |
2364 | kfree(ra); | 2407 | kfree(ra); |
2408 | trans = btrfs_start_transaction(BTRFS_I(inode)->root, 1); | ||
2409 | if (trans) { | ||
2410 | btrfs_add_ordered_inode(inode); | ||
2411 | btrfs_end_transaction(trans, BTRFS_I(inode)->root); | ||
2412 | mark_inode_dirty(inode); | ||
2413 | } | ||
2365 | mutex_unlock(&inode->i_mutex); | 2414 | mutex_unlock(&inode->i_mutex); |
2366 | return 0; | 2415 | return 0; |
2416 | |||
2417 | truncate_racing: | ||
2418 | vmtruncate(inode, inode->i_size); | ||
2419 | balance_dirty_pages_ratelimited_nr(inode->i_mapping, | ||
2420 | total_read); | ||
2421 | goto out_unlock; | ||
2367 | } | 2422 | } |
2368 | 2423 | ||
2369 | /* | 2424 | /* |
@@ -2466,6 +2521,27 @@ out: | |||
2466 | return 0; | 2521 | return 0; |
2467 | } | 2522 | } |
2468 | 2523 | ||
2524 | static int noinline del_extent_zero(struct btrfs_root *extent_root, | ||
2525 | struct btrfs_path *path, | ||
2526 | struct btrfs_key *extent_key) | ||
2527 | { | ||
2528 | int ret; | ||
2529 | struct btrfs_trans_handle *trans; | ||
2530 | |||
2531 | trans = btrfs_start_transaction(extent_root, 1); | ||
2532 | ret = btrfs_search_slot(trans, extent_root, extent_key, path, -1, 1); | ||
2533 | if (ret > 0) { | ||
2534 | ret = -EIO; | ||
2535 | goto out; | ||
2536 | } | ||
2537 | if (ret < 0) | ||
2538 | goto out; | ||
2539 | ret = btrfs_del_item(trans, extent_root, path); | ||
2540 | out: | ||
2541 | btrfs_end_transaction(trans, extent_root); | ||
2542 | return ret; | ||
2543 | } | ||
2544 | |||
2469 | static int noinline relocate_one_extent(struct btrfs_root *extent_root, | 2545 | static int noinline relocate_one_extent(struct btrfs_root *extent_root, |
2470 | struct btrfs_path *path, | 2546 | struct btrfs_path *path, |
2471 | struct btrfs_key *extent_key) | 2547 | struct btrfs_key *extent_key) |
@@ -2477,6 +2553,10 @@ static int noinline relocate_one_extent(struct btrfs_root *extent_root, | |||
2477 | u32 item_size; | 2553 | u32 item_size; |
2478 | int ret = 0; | 2554 | int ret = 0; |
2479 | 2555 | ||
2556 | if (extent_key->objectid == 0) { | ||
2557 | ret = del_extent_zero(extent_root, path, extent_key); | ||
2558 | goto out; | ||
2559 | } | ||
2480 | key.objectid = extent_key->objectid; | 2560 | key.objectid = extent_key->objectid; |
2481 | key.type = BTRFS_EXTENT_REF_KEY; | 2561 | key.type = BTRFS_EXTENT_REF_KEY; |
2482 | key.offset = 0; | 2562 | key.offset = 0; |
@@ -2490,15 +2570,24 @@ static int noinline relocate_one_extent(struct btrfs_root *extent_root, | |||
2490 | ret = 0; | 2570 | ret = 0; |
2491 | leaf = path->nodes[0]; | 2571 | leaf = path->nodes[0]; |
2492 | nritems = btrfs_header_nritems(leaf); | 2572 | nritems = btrfs_header_nritems(leaf); |
2493 | if (path->slots[0] == nritems) | 2573 | if (path->slots[0] == nritems) { |
2494 | goto out; | 2574 | ret = btrfs_next_leaf(extent_root, path); |
2575 | if (ret > 0) { | ||
2576 | ret = 0; | ||
2577 | goto out; | ||
2578 | } | ||
2579 | if (ret < 0) | ||
2580 | goto out; | ||
2581 | } | ||
2495 | 2582 | ||
2496 | btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); | 2583 | btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); |
2497 | if (found_key.objectid != extent_key->objectid) | 2584 | if (found_key.objectid != extent_key->objectid) { |
2498 | break; | 2585 | break; |
2586 | } | ||
2499 | 2587 | ||
2500 | if (found_key.type != BTRFS_EXTENT_REF_KEY) | 2588 | if (found_key.type != BTRFS_EXTENT_REF_KEY) { |
2501 | break; | 2589 | break; |
2590 | } | ||
2502 | 2591 | ||
2503 | key.offset = found_key.offset + 1; | 2592 | key.offset = found_key.offset + 1; |
2504 | item_size = btrfs_item_size_nr(leaf, path->slots[0]); | 2593 | item_size = btrfs_item_size_nr(leaf, path->slots[0]); |
@@ -2519,7 +2608,7 @@ static u64 update_block_group_flags(struct btrfs_root *root, u64 flags) | |||
2519 | u64 stripped = BTRFS_BLOCK_GROUP_RAID0 | | 2608 | u64 stripped = BTRFS_BLOCK_GROUP_RAID0 | |
2520 | BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID10; | 2609 | BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID10; |
2521 | 2610 | ||
2522 | num_devices = btrfs_super_num_devices(&root->fs_info->super_copy); | 2611 | num_devices = root->fs_info->fs_devices->num_devices; |
2523 | if (num_devices == 1) { | 2612 | if (num_devices == 1) { |
2524 | stripped |= BTRFS_BLOCK_GROUP_DUP; | 2613 | stripped |= BTRFS_BLOCK_GROUP_DUP; |
2525 | stripped = flags & ~stripped; | 2614 | stripped = flags & ~stripped; |
@@ -2535,9 +2624,6 @@ static u64 update_block_group_flags(struct btrfs_root *root, u64 flags) | |||
2535 | return flags; | 2624 | return flags; |
2536 | } else { | 2625 | } else { |
2537 | /* they already had raid on here, just return */ | 2626 | /* they already had raid on here, just return */ |
2538 | if ((flags & BTRFS_BLOCK_GROUP_DUP) && | ||
2539 | (flags & BTRFS_BLOCK_GROUP_RAID1)) { | ||
2540 | } | ||
2541 | if (flags & stripped) | 2627 | if (flags & stripped) |
2542 | return flags; | 2628 | return flags; |
2543 | 2629 | ||
@@ -2570,7 +2656,7 @@ int btrfs_shrink_extent_tree(struct btrfs_root *root, u64 shrink_start) | |||
2570 | struct extent_buffer *leaf; | 2656 | struct extent_buffer *leaf; |
2571 | u32 nritems; | 2657 | u32 nritems; |
2572 | int ret; | 2658 | int ret; |
2573 | int progress = 0; | 2659 | int progress; |
2574 | 2660 | ||
2575 | shrink_block_group = btrfs_lookup_block_group(root->fs_info, | 2661 | shrink_block_group = btrfs_lookup_block_group(root->fs_info, |
2576 | shrink_start); | 2662 | shrink_start); |
@@ -2597,6 +2683,7 @@ again: | |||
2597 | shrink_block_group->ro = 1; | 2683 | shrink_block_group->ro = 1; |
2598 | 2684 | ||
2599 | total_found = 0; | 2685 | total_found = 0; |
2686 | progress = 0; | ||
2600 | key.objectid = shrink_start; | 2687 | key.objectid = shrink_start; |
2601 | key.offset = 0; | 2688 | key.offset = 0; |
2602 | key.type = 0; | 2689 | key.type = 0; |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index f7beb9b0d37a..b437d3bdf95e 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -2194,6 +2194,8 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page, | |||
2194 | again: | 2194 | again: |
2195 | spin_lock(&em_tree->lock); | 2195 | spin_lock(&em_tree->lock); |
2196 | em = lookup_extent_mapping(em_tree, start, len); | 2196 | em = lookup_extent_mapping(em_tree, start, len); |
2197 | if (em) | ||
2198 | em->bdev = root->fs_info->fs_devices->latest_bdev; | ||
2197 | spin_unlock(&em_tree->lock); | 2199 | spin_unlock(&em_tree->lock); |
2198 | 2200 | ||
2199 | if (em) { | 2201 | if (em) { |
@@ -2212,7 +2214,7 @@ again: | |||
2212 | 2214 | ||
2213 | em->start = EXTENT_MAP_HOLE; | 2215 | em->start = EXTENT_MAP_HOLE; |
2214 | em->len = (u64)-1; | 2216 | em->len = (u64)-1; |
2215 | em->bdev = inode->i_sb->s_bdev; | 2217 | em->bdev = root->fs_info->fs_devices->latest_bdev; |
2216 | ret = btrfs_lookup_file_extent(trans, root, path, | 2218 | ret = btrfs_lookup_file_extent(trans, root, path, |
2217 | objectid, start, trans != NULL); | 2219 | objectid, start, trans != NULL); |
2218 | if (ret < 0) { | 2220 | if (ret < 0) { |
@@ -3101,6 +3103,27 @@ out: | |||
3101 | return ret; | 3103 | return ret; |
3102 | } | 3104 | } |
3103 | 3105 | ||
3106 | long btrfs_ioctl_rm_dev(struct btrfs_root *root, void __user *arg) | ||
3107 | { | ||
3108 | struct btrfs_ioctl_vol_args *vol_args; | ||
3109 | int ret; | ||
3110 | |||
3111 | vol_args = kmalloc(sizeof(*vol_args), GFP_NOFS); | ||
3112 | |||
3113 | if (!vol_args) | ||
3114 | return -ENOMEM; | ||
3115 | |||
3116 | if (copy_from_user(vol_args, arg, sizeof(*vol_args))) { | ||
3117 | ret = -EFAULT; | ||
3118 | goto out; | ||
3119 | } | ||
3120 | ret = btrfs_rm_device(root, vol_args->name); | ||
3121 | |||
3122 | out: | ||
3123 | kfree(vol_args); | ||
3124 | return ret; | ||
3125 | } | ||
3126 | |||
3104 | int dup_item_to_inode(struct btrfs_trans_handle *trans, | 3127 | int dup_item_to_inode(struct btrfs_trans_handle *trans, |
3105 | struct btrfs_root *root, | 3128 | struct btrfs_root *root, |
3106 | struct btrfs_path *path, | 3129 | struct btrfs_path *path, |
@@ -3294,6 +3317,8 @@ long btrfs_ioctl(struct file *file, unsigned int | |||
3294 | return btrfs_ioctl_resize(root, (void __user *)arg); | 3317 | return btrfs_ioctl_resize(root, (void __user *)arg); |
3295 | case BTRFS_IOC_ADD_DEV: | 3318 | case BTRFS_IOC_ADD_DEV: |
3296 | return btrfs_ioctl_add_dev(root, (void __user *)arg); | 3319 | return btrfs_ioctl_add_dev(root, (void __user *)arg); |
3320 | case BTRFS_IOC_RM_DEV: | ||
3321 | return btrfs_ioctl_rm_dev(root, (void __user *)arg); | ||
3297 | case BTRFS_IOC_BALANCE: | 3322 | case BTRFS_IOC_BALANCE: |
3298 | return btrfs_balance(root->fs_info->dev_root); | 3323 | return btrfs_balance(root->fs_info->dev_root); |
3299 | case BTRFS_IOC_CLONE: | 3324 | case BTRFS_IOC_CLONE: |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 7153dfaa3404..020e5a83e31f 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -315,24 +315,12 @@ static void btrfs_write_super(struct super_block *sb) | |||
315 | sb->s_dirt = 0; | 315 | sb->s_dirt = 0; |
316 | } | 316 | } |
317 | 317 | ||
318 | /* | 318 | static int btrfs_test_super(struct super_block *s, void *data) |
319 | * This is almost a copy of get_sb_bdev in fs/super.c. | ||
320 | * We need the local copy to allow direct mounting of | ||
321 | * subvolumes, but this could be easily integrated back | ||
322 | * into the generic version. --hch | ||
323 | */ | ||
324 | |||
325 | /* start copy & paste */ | ||
326 | static int set_bdev_super(struct super_block *s, void *data) | ||
327 | { | 319 | { |
328 | s->s_bdev = data; | 320 | struct btrfs_fs_devices *test_fs_devices = data; |
329 | s->s_dev = s->s_bdev->bd_dev; | 321 | struct btrfs_root *root = btrfs_sb(s); |
330 | return 0; | ||
331 | } | ||
332 | 322 | ||
333 | static int test_bdev_super(struct super_block *s, void *data) | 323 | return root->fs_info->fs_devices == test_fs_devices; |
334 | { | ||
335 | return (void *)s->s_bdev == data; | ||
336 | } | 324 | } |
337 | 325 | ||
338 | int btrfs_get_sb_bdev(struct file_system_type *fs_type, | 326 | int btrfs_get_sb_bdev(struct file_system_type *fs_type, |
@@ -354,14 +342,9 @@ int btrfs_get_sb_bdev(struct file_system_type *fs_type, | |||
354 | return error; | 342 | return error; |
355 | 343 | ||
356 | bdev = fs_devices->lowest_bdev; | 344 | bdev = fs_devices->lowest_bdev; |
357 | /* | 345 | btrfs_lock_volumes(); |
358 | * once the super is inserted into the list by sget, s_umount | 346 | s = sget(fs_type, btrfs_test_super, set_anon_super, fs_devices); |
359 | * will protect the lockfs code from trying to start a snapshot | 347 | btrfs_unlock_volumes(); |
360 | * while we are mounting | ||
361 | */ | ||
362 | down(&bdev->bd_mount_sem); | ||
363 | s = sget(fs_type, test_bdev_super, set_bdev_super, bdev); | ||
364 | up(&bdev->bd_mount_sem); | ||
365 | if (IS_ERR(s)) | 348 | if (IS_ERR(s)) |
366 | goto error_s; | 349 | goto error_s; |
367 | 350 | ||
@@ -373,13 +356,11 @@ int btrfs_get_sb_bdev(struct file_system_type *fs_type, | |||
373 | goto error_bdev; | 356 | goto error_bdev; |
374 | } | 357 | } |
375 | 358 | ||
376 | close_bdev_excl(bdev); | ||
377 | } else { | 359 | } else { |
378 | char b[BDEVNAME_SIZE]; | 360 | char b[BDEVNAME_SIZE]; |
379 | 361 | ||
380 | s->s_flags = flags; | 362 | s->s_flags = flags; |
381 | strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id)); | 363 | strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id)); |
382 | sb_set_blocksize(s, block_size(bdev)); | ||
383 | error = btrfs_fill_super(s, fs_devices, data, | 364 | error = btrfs_fill_super(s, fs_devices, data, |
384 | flags & MS_SILENT ? 1 : 0); | 365 | flags & MS_SILENT ? 1 : 0); |
385 | if (error) { | 366 | if (error) { |
@@ -458,7 +439,7 @@ static struct file_system_type btrfs_fs_type = { | |||
458 | .owner = THIS_MODULE, | 439 | .owner = THIS_MODULE, |
459 | .name = "btrfs", | 440 | .name = "btrfs", |
460 | .get_sb = btrfs_get_sb, | 441 | .get_sb = btrfs_get_sb, |
461 | .kill_sb = kill_block_super, | 442 | .kill_sb = kill_anon_super, |
462 | .fs_flags = FS_REQUIRES_DEV, | 443 | .fs_flags = FS_REQUIRES_DEV, |
463 | }; | 444 | }; |
464 | 445 | ||
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 9826942fa18a..57746c11eae3 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -738,9 +738,8 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
738 | chunk_root->node->start); | 738 | chunk_root->node->start); |
739 | btrfs_set_super_chunk_root_level(&root->fs_info->super_copy, | 739 | btrfs_set_super_chunk_root_level(&root->fs_info->super_copy, |
740 | btrfs_header_level(chunk_root->node)); | 740 | btrfs_header_level(chunk_root->node)); |
741 | write_extent_buffer(root->fs_info->sb_buffer, | 741 | memcpy(&root->fs_info->super_for_commit, &root->fs_info->super_copy, |
742 | &root->fs_info->super_copy, 0, | 742 | sizeof(root->fs_info->super_copy)); |
743 | sizeof(root->fs_info->super_copy)); | ||
744 | 743 | ||
745 | btrfs_copy_pinned(root, pinned_copy); | 744 | btrfs_copy_pinned(root, pinned_copy); |
746 | 745 | ||
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index b38187573108..55da5f0c56e3 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -45,6 +45,16 @@ struct map_lookup { | |||
45 | static DEFINE_MUTEX(uuid_mutex); | 45 | static DEFINE_MUTEX(uuid_mutex); |
46 | static LIST_HEAD(fs_uuids); | 46 | static LIST_HEAD(fs_uuids); |
47 | 47 | ||
48 | void btrfs_lock_volumes(void) | ||
49 | { | ||
50 | mutex_lock(&uuid_mutex); | ||
51 | } | ||
52 | |||
53 | void btrfs_unlock_volumes(void) | ||
54 | { | ||
55 | mutex_unlock(&uuid_mutex); | ||
56 | } | ||
57 | |||
48 | int btrfs_cleanup_fs_uuids(void) | 58 | int btrfs_cleanup_fs_uuids(void) |
49 | { | 59 | { |
50 | struct btrfs_fs_devices *fs_devices; | 60 | struct btrfs_fs_devices *fs_devices; |
@@ -193,12 +203,14 @@ int btrfs_open_devices(struct btrfs_fs_devices *fs_devices, | |||
193 | ret = PTR_ERR(bdev); | 203 | ret = PTR_ERR(bdev); |
194 | goto fail; | 204 | goto fail; |
195 | } | 205 | } |
206 | set_blocksize(bdev, 4096); | ||
196 | if (device->devid == fs_devices->latest_devid) | 207 | if (device->devid == fs_devices->latest_devid) |
197 | fs_devices->latest_bdev = bdev; | 208 | fs_devices->latest_bdev = bdev; |
198 | if (device->devid == fs_devices->lowest_devid) { | 209 | if (device->devid == fs_devices->lowest_devid) { |
199 | fs_devices->lowest_bdev = bdev; | 210 | fs_devices->lowest_bdev = bdev; |
200 | } | 211 | } |
201 | device->bdev = bdev; | 212 | device->bdev = bdev; |
213 | |||
202 | } | 214 | } |
203 | mutex_unlock(&uuid_mutex); | 215 | mutex_unlock(&uuid_mutex); |
204 | return 0; | 216 | return 0; |
@@ -393,6 +405,9 @@ int btrfs_free_dev_extent(struct btrfs_trans_handle *trans, | |||
393 | struct btrfs_path *path; | 405 | struct btrfs_path *path; |
394 | struct btrfs_root *root = device->dev_root; | 406 | struct btrfs_root *root = device->dev_root; |
395 | struct btrfs_key key; | 407 | struct btrfs_key key; |
408 | struct btrfs_key found_key; | ||
409 | struct extent_buffer *leaf = NULL; | ||
410 | struct btrfs_dev_extent *extent = NULL; | ||
396 | 411 | ||
397 | path = btrfs_alloc_path(); | 412 | path = btrfs_alloc_path(); |
398 | if (!path) | 413 | if (!path) |
@@ -403,8 +418,25 @@ int btrfs_free_dev_extent(struct btrfs_trans_handle *trans, | |||
403 | key.type = BTRFS_DEV_EXTENT_KEY; | 418 | key.type = BTRFS_DEV_EXTENT_KEY; |
404 | 419 | ||
405 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); | 420 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); |
421 | if (ret > 0) { | ||
422 | ret = btrfs_previous_item(root, path, key.objectid, | ||
423 | BTRFS_DEV_EXTENT_KEY); | ||
424 | BUG_ON(ret); | ||
425 | leaf = path->nodes[0]; | ||
426 | btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); | ||
427 | extent = btrfs_item_ptr(leaf, path->slots[0], | ||
428 | struct btrfs_dev_extent); | ||
429 | BUG_ON(found_key.offset > start || found_key.offset + | ||
430 | btrfs_dev_extent_length(leaf, extent) < start); | ||
431 | ret = 0; | ||
432 | } else if (ret == 0) { | ||
433 | leaf = path->nodes[0]; | ||
434 | extent = btrfs_item_ptr(leaf, path->slots[0], | ||
435 | struct btrfs_dev_extent); | ||
436 | } | ||
406 | BUG_ON(ret); | 437 | BUG_ON(ret); |
407 | 438 | ||
439 | device->bytes_used -= btrfs_dev_extent_length(leaf, extent); | ||
408 | ret = btrfs_del_item(trans, root, path); | 440 | ret = btrfs_del_item(trans, root, path); |
409 | BUG_ON(ret); | 441 | BUG_ON(ret); |
410 | 442 | ||
@@ -593,6 +625,170 @@ out: | |||
593 | return ret; | 625 | return ret; |
594 | } | 626 | } |
595 | 627 | ||
628 | static int btrfs_rm_dev_item(struct btrfs_root *root, | ||
629 | struct btrfs_device *device) | ||
630 | { | ||
631 | int ret; | ||
632 | struct btrfs_path *path; | ||
633 | struct block_device *bdev = device->bdev; | ||
634 | struct btrfs_device *next_dev; | ||
635 | struct btrfs_key key; | ||
636 | u64 total_bytes; | ||
637 | struct btrfs_fs_devices *fs_devices; | ||
638 | struct btrfs_trans_handle *trans; | ||
639 | |||
640 | root = root->fs_info->chunk_root; | ||
641 | |||
642 | path = btrfs_alloc_path(); | ||
643 | if (!path) | ||
644 | return -ENOMEM; | ||
645 | |||
646 | trans = btrfs_start_transaction(root, 1); | ||
647 | key.objectid = BTRFS_DEV_ITEMS_OBJECTID; | ||
648 | key.type = BTRFS_DEV_ITEM_KEY; | ||
649 | key.offset = device->devid; | ||
650 | |||
651 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); | ||
652 | if (ret < 0) | ||
653 | goto out; | ||
654 | |||
655 | if (ret > 0) { | ||
656 | ret = -ENOENT; | ||
657 | goto out; | ||
658 | } | ||
659 | |||
660 | ret = btrfs_del_item(trans, root, path); | ||
661 | if (ret) | ||
662 | goto out; | ||
663 | |||
664 | /* | ||
665 | * at this point, the device is zero sized. We want to | ||
666 | * remove it from the devices list and zero out the old super | ||
667 | */ | ||
668 | list_del_init(&device->dev_list); | ||
669 | list_del_init(&device->dev_alloc_list); | ||
670 | fs_devices = root->fs_info->fs_devices; | ||
671 | |||
672 | next_dev = list_entry(fs_devices->devices.next, struct btrfs_device, | ||
673 | dev_list); | ||
674 | if (bdev == fs_devices->lowest_bdev) | ||
675 | fs_devices->lowest_bdev = next_dev->bdev; | ||
676 | if (bdev == root->fs_info->sb->s_bdev) | ||
677 | root->fs_info->sb->s_bdev = next_dev->bdev; | ||
678 | if (bdev == fs_devices->latest_bdev) | ||
679 | fs_devices->latest_bdev = next_dev->bdev; | ||
680 | |||
681 | total_bytes = btrfs_super_total_bytes(&root->fs_info->super_copy); | ||
682 | btrfs_set_super_total_bytes(&root->fs_info->super_copy, | ||
683 | total_bytes - device->total_bytes); | ||
684 | |||
685 | total_bytes = btrfs_super_num_devices(&root->fs_info->super_copy); | ||
686 | btrfs_set_super_num_devices(&root->fs_info->super_copy, | ||
687 | total_bytes - 1); | ||
688 | out: | ||
689 | btrfs_free_path(path); | ||
690 | btrfs_commit_transaction(trans, root); | ||
691 | return ret; | ||
692 | } | ||
693 | |||
694 | int btrfs_rm_device(struct btrfs_root *root, char *device_path) | ||
695 | { | ||
696 | struct btrfs_device *device; | ||
697 | struct block_device *bdev; | ||
698 | struct buffer_head *bh; | ||
699 | struct btrfs_super_block *disk_super; | ||
700 | u64 all_avail; | ||
701 | u64 devid; | ||
702 | int ret = 0; | ||
703 | |||
704 | mutex_lock(&root->fs_info->fs_mutex); | ||
705 | mutex_lock(&uuid_mutex); | ||
706 | |||
707 | all_avail = root->fs_info->avail_data_alloc_bits | | ||
708 | root->fs_info->avail_system_alloc_bits | | ||
709 | root->fs_info->avail_metadata_alloc_bits; | ||
710 | |||
711 | if ((all_avail & BTRFS_BLOCK_GROUP_RAID10) && | ||
712 | root->fs_info->fs_devices->num_devices <= 4) { | ||
713 | printk("btrfs: unable to go below four devices on raid10\n"); | ||
714 | ret = -EINVAL; | ||
715 | goto out; | ||
716 | } | ||
717 | |||
718 | if ((all_avail & BTRFS_BLOCK_GROUP_RAID1) && | ||
719 | root->fs_info->fs_devices->num_devices <= 2) { | ||
720 | printk("btrfs: unable to go below two devices on raid1\n"); | ||
721 | ret = -EINVAL; | ||
722 | goto out; | ||
723 | } | ||
724 | |||
725 | bdev = open_bdev_excl(device_path, 0, root->fs_info->bdev_holder); | ||
726 | if (IS_ERR(bdev)) { | ||
727 | ret = PTR_ERR(bdev); | ||
728 | goto out; | ||
729 | } | ||
730 | |||
731 | bh = __bread(bdev, BTRFS_SUPER_INFO_OFFSET / 4096, 4096); | ||
732 | if (!bh) { | ||
733 | ret = -EIO; | ||
734 | goto error_close; | ||
735 | } | ||
736 | disk_super = (struct btrfs_super_block *)bh->b_data; | ||
737 | if (strncmp((char *)(&disk_super->magic), BTRFS_MAGIC, | ||
738 | sizeof(disk_super->magic))) { | ||
739 | ret = -ENOENT; | ||
740 | goto error_brelse; | ||
741 | } | ||
742 | if (memcmp(disk_super->fsid, root->fs_info->fsid, BTRFS_FSID_SIZE)) { | ||
743 | ret = -ENOENT; | ||
744 | goto error_brelse; | ||
745 | } | ||
746 | devid = le64_to_cpu(disk_super->dev_item.devid); | ||
747 | device = btrfs_find_device(root, devid, NULL); | ||
748 | if (!device) { | ||
749 | ret = -ENOENT; | ||
750 | goto error_brelse; | ||
751 | } | ||
752 | |||
753 | root->fs_info->fs_devices->num_devices--; | ||
754 | |||
755 | ret = btrfs_shrink_device(device, 0); | ||
756 | if (ret) | ||
757 | goto error_brelse; | ||
758 | |||
759 | |||
760 | ret = btrfs_rm_dev_item(root->fs_info->chunk_root, device); | ||
761 | if (ret) | ||
762 | goto error_brelse; | ||
763 | |||
764 | /* make sure this device isn't detected as part of the FS anymore */ | ||
765 | memset(&disk_super->magic, 0, sizeof(disk_super->magic)); | ||
766 | set_buffer_dirty(bh); | ||
767 | sync_dirty_buffer(bh); | ||
768 | |||
769 | brelse(bh); | ||
770 | |||
771 | /* one close for the device struct or super_block */ | ||
772 | close_bdev_excl(device->bdev); | ||
773 | |||
774 | /* one close for us */ | ||
775 | close_bdev_excl(device->bdev); | ||
776 | |||
777 | kfree(device->name); | ||
778 | kfree(device); | ||
779 | ret = 0; | ||
780 | goto out; | ||
781 | |||
782 | error_brelse: | ||
783 | brelse(bh); | ||
784 | error_close: | ||
785 | close_bdev_excl(bdev); | ||
786 | out: | ||
787 | mutex_unlock(&uuid_mutex); | ||
788 | mutex_unlock(&root->fs_info->fs_mutex); | ||
789 | return ret; | ||
790 | } | ||
791 | |||
596 | int btrfs_init_new_device(struct btrfs_root *root, char *device_path) | 792 | int btrfs_init_new_device(struct btrfs_root *root, char *device_path) |
597 | { | 793 | { |
598 | struct btrfs_trans_handle *trans; | 794 | struct btrfs_trans_handle *trans; |
@@ -831,13 +1027,17 @@ int btrfs_relocate_chunk(struct btrfs_root *root, | |||
831 | em = lookup_extent_mapping(em_tree, chunk_offset, 1); | 1027 | em = lookup_extent_mapping(em_tree, chunk_offset, 1); |
832 | spin_unlock(&em_tree->lock); | 1028 | spin_unlock(&em_tree->lock); |
833 | 1029 | ||
834 | BUG_ON(em->start > chunk_offset || em->start + em->len < chunk_offset); | 1030 | BUG_ON(em->start > chunk_offset || |
1031 | em->start + em->len < chunk_offset); | ||
835 | map = (struct map_lookup *)em->bdev; | 1032 | map = (struct map_lookup *)em->bdev; |
836 | 1033 | ||
837 | for (i = 0; i < map->num_stripes; i++) { | 1034 | for (i = 0; i < map->num_stripes; i++) { |
838 | ret = btrfs_free_dev_extent(trans, map->stripes[i].dev, | 1035 | ret = btrfs_free_dev_extent(trans, map->stripes[i].dev, |
839 | map->stripes[i].physical); | 1036 | map->stripes[i].physical); |
840 | BUG_ON(ret); | 1037 | BUG_ON(ret); |
1038 | |||
1039 | ret = btrfs_update_device(trans, map->stripes[i].dev); | ||
1040 | BUG_ON(ret); | ||
841 | } | 1041 | } |
842 | ret = btrfs_free_chunk(trans, root, chunk_tree, chunk_objectid, | 1042 | ret = btrfs_free_chunk(trans, root, chunk_tree, chunk_objectid, |
843 | chunk_offset); | 1043 | chunk_offset); |
@@ -847,11 +1047,8 @@ int btrfs_relocate_chunk(struct btrfs_root *root, | |||
847 | if (map->type & BTRFS_BLOCK_GROUP_SYSTEM) { | 1047 | if (map->type & BTRFS_BLOCK_GROUP_SYSTEM) { |
848 | ret = btrfs_del_sys_chunk(root, chunk_objectid, chunk_offset); | 1048 | ret = btrfs_del_sys_chunk(root, chunk_objectid, chunk_offset); |
849 | BUG_ON(ret); | 1049 | BUG_ON(ret); |
850 | goto out; | ||
851 | } | 1050 | } |
852 | 1051 | ||
853 | |||
854 | |||
855 | spin_lock(&em_tree->lock); | 1052 | spin_lock(&em_tree->lock); |
856 | remove_extent_mapping(em_tree, em); | 1053 | remove_extent_mapping(em_tree, em); |
857 | kfree(map); | 1054 | kfree(map); |
@@ -861,7 +1058,6 @@ int btrfs_relocate_chunk(struct btrfs_root *root, | |||
861 | free_extent_map(em); | 1058 | free_extent_map(em); |
862 | spin_unlock(&em_tree->lock); | 1059 | spin_unlock(&em_tree->lock); |
863 | 1060 | ||
864 | out: | ||
865 | /* once for us */ | 1061 | /* once for us */ |
866 | free_extent_map(em); | 1062 | free_extent_map(em); |
867 | 1063 | ||
@@ -1449,7 +1645,7 @@ again: | |||
1449 | return 0; | 1645 | return 0; |
1450 | 1646 | ||
1451 | if (!em) { | 1647 | if (!em) { |
1452 | printk("unable to find logical %Lu\n", logical); | 1648 | printk("unable to find logical %Lu len %Lu\n", logical, *length); |
1453 | BUG(); | 1649 | BUG(); |
1454 | } | 1650 | } |
1455 | 1651 | ||
@@ -1712,6 +1908,7 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key, | |||
1712 | 1908 | ||
1713 | logical = key->offset; | 1909 | logical = key->offset; |
1714 | length = btrfs_chunk_length(leaf, chunk); | 1910 | length = btrfs_chunk_length(leaf, chunk); |
1911 | |||
1715 | spin_lock(&map_tree->map_tree.lock); | 1912 | spin_lock(&map_tree->map_tree.lock); |
1716 | em = lookup_extent_mapping(&map_tree->map_tree, logical, 1); | 1913 | em = lookup_extent_mapping(&map_tree->map_tree, logical, 1); |
1717 | spin_unlock(&map_tree->map_tree.lock); | 1914 | spin_unlock(&map_tree->map_tree.lock); |
@@ -1845,7 +2042,7 @@ int btrfs_read_super_device(struct btrfs_root *root, struct extent_buffer *buf) | |||
1845 | int btrfs_read_sys_array(struct btrfs_root *root) | 2042 | int btrfs_read_sys_array(struct btrfs_root *root) |
1846 | { | 2043 | { |
1847 | struct btrfs_super_block *super_copy = &root->fs_info->super_copy; | 2044 | struct btrfs_super_block *super_copy = &root->fs_info->super_copy; |
1848 | struct extent_buffer *sb = root->fs_info->sb_buffer; | 2045 | struct extent_buffer *sb; |
1849 | struct btrfs_disk_key *disk_key; | 2046 | struct btrfs_disk_key *disk_key; |
1850 | struct btrfs_chunk *chunk; | 2047 | struct btrfs_chunk *chunk; |
1851 | u8 *ptr; | 2048 | u8 *ptr; |
@@ -1857,6 +2054,12 @@ int btrfs_read_sys_array(struct btrfs_root *root) | |||
1857 | u32 cur; | 2054 | u32 cur; |
1858 | struct btrfs_key key; | 2055 | struct btrfs_key key; |
1859 | 2056 | ||
2057 | sb = btrfs_find_create_tree_block(root, BTRFS_SUPER_INFO_OFFSET, | ||
2058 | BTRFS_SUPER_INFO_SIZE); | ||
2059 | if (!sb) | ||
2060 | return -ENOMEM; | ||
2061 | btrfs_set_buffer_uptodate(sb); | ||
2062 | write_extent_buffer(sb, super_copy, 0, BTRFS_SUPER_INFO_SIZE); | ||
1860 | array_size = btrfs_super_sys_array_size(super_copy); | 2063 | array_size = btrfs_super_sys_array_size(super_copy); |
1861 | 2064 | ||
1862 | ptr = super_copy->sys_chunk_array; | 2065 | ptr = super_copy->sys_chunk_array; |
@@ -1867,8 +2070,7 @@ int btrfs_read_sys_array(struct btrfs_root *root) | |||
1867 | disk_key = (struct btrfs_disk_key *)ptr; | 2070 | disk_key = (struct btrfs_disk_key *)ptr; |
1868 | btrfs_disk_key_to_cpu(&key, disk_key); | 2071 | btrfs_disk_key_to_cpu(&key, disk_key); |
1869 | 2072 | ||
1870 | len = sizeof(*disk_key); | 2073 | len = sizeof(*disk_key); ptr += len; |
1871 | ptr += len; | ||
1872 | sb_ptr += len; | 2074 | sb_ptr += len; |
1873 | cur += len; | 2075 | cur += len; |
1874 | 2076 | ||
@@ -1887,6 +2089,7 @@ int btrfs_read_sys_array(struct btrfs_root *root) | |||
1887 | sb_ptr += len; | 2089 | sb_ptr += len; |
1888 | cur += len; | 2090 | cur += len; |
1889 | } | 2091 | } |
2092 | free_extent_buffer(sb); | ||
1890 | return ret; | 2093 | return ret; |
1891 | } | 2094 | } |
1892 | 2095 | ||
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index a9663e92bb14..0f94a69e6eb6 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h | |||
@@ -125,6 +125,7 @@ int btrfs_close_devices(struct btrfs_fs_devices *fs_devices); | |||
125 | int btrfs_add_device(struct btrfs_trans_handle *trans, | 125 | int btrfs_add_device(struct btrfs_trans_handle *trans, |
126 | struct btrfs_root *root, | 126 | struct btrfs_root *root, |
127 | struct btrfs_device *device); | 127 | struct btrfs_device *device); |
128 | int btrfs_rm_device(struct btrfs_root *root, char *device_path); | ||
128 | int btrfs_cleanup_fs_uuids(void); | 129 | int btrfs_cleanup_fs_uuids(void); |
129 | int btrfs_num_copies(struct btrfs_mapping_tree *map_tree, u64 logical, u64 len); | 130 | int btrfs_num_copies(struct btrfs_mapping_tree *map_tree, u64 logical, u64 len); |
130 | int btrfs_unplug_page(struct btrfs_mapping_tree *map_tree, | 131 | int btrfs_unplug_page(struct btrfs_mapping_tree *map_tree, |
@@ -136,4 +137,6 @@ struct btrfs_device *btrfs_find_device(struct btrfs_root *root, u64 devid, | |||
136 | int btrfs_shrink_device(struct btrfs_device *device, u64 new_size); | 137 | int btrfs_shrink_device(struct btrfs_device *device, u64 new_size); |
137 | int btrfs_init_new_device(struct btrfs_root *root, char *path); | 138 | int btrfs_init_new_device(struct btrfs_root *root, char *path); |
138 | int btrfs_balance(struct btrfs_root *dev_root); | 139 | int btrfs_balance(struct btrfs_root *dev_root); |
140 | void btrfs_unlock_volumes(void); | ||
141 | void btrfs_lock_volumes(void); | ||
139 | #endif | 142 | #endif |