diff options
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r-- | fs/btrfs/volumes.c | 93 |
1 files changed, 50 insertions, 43 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 92e586bc8004..4def1fdbf755 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -108,6 +108,44 @@ static noinline struct btrfs_fs_devices *find_fsid(u8 *fsid) | |||
108 | return NULL; | 108 | return NULL; |
109 | } | 109 | } |
110 | 110 | ||
111 | static int | ||
112 | btrfs_get_bdev_and_sb(const char *device_path, fmode_t flags, void *holder, | ||
113 | int flush, struct block_device **bdev, | ||
114 | struct buffer_head **bh) | ||
115 | { | ||
116 | int ret; | ||
117 | |||
118 | *bdev = blkdev_get_by_path(device_path, flags, holder); | ||
119 | |||
120 | if (IS_ERR(*bdev)) { | ||
121 | ret = PTR_ERR(*bdev); | ||
122 | printk(KERN_INFO "btrfs: open %s failed\n", device_path); | ||
123 | goto error; | ||
124 | } | ||
125 | |||
126 | if (flush) | ||
127 | filemap_write_and_wait((*bdev)->bd_inode->i_mapping); | ||
128 | ret = set_blocksize(*bdev, 4096); | ||
129 | if (ret) { | ||
130 | blkdev_put(*bdev, flags); | ||
131 | goto error; | ||
132 | } | ||
133 | invalidate_bdev(*bdev); | ||
134 | *bh = btrfs_read_dev_super(*bdev); | ||
135 | if (!*bh) { | ||
136 | ret = -EINVAL; | ||
137 | blkdev_put(*bdev, flags); | ||
138 | goto error; | ||
139 | } | ||
140 | |||
141 | return 0; | ||
142 | |||
143 | error: | ||
144 | *bdev = NULL; | ||
145 | *bh = NULL; | ||
146 | return ret; | ||
147 | } | ||
148 | |||
111 | static void requeue_list(struct btrfs_pending_bios *pending_bios, | 149 | static void requeue_list(struct btrfs_pending_bios *pending_bios, |
112 | struct bio *head, struct bio *tail) | 150 | struct bio *head, struct bio *tail) |
113 | { | 151 | { |
@@ -637,18 +675,10 @@ static int __btrfs_open_devices(struct btrfs_fs_devices *fs_devices, | |||
637 | if (!device->name) | 675 | if (!device->name) |
638 | continue; | 676 | continue; |
639 | 677 | ||
640 | bdev = blkdev_get_by_path(device->name->str, flags, holder); | 678 | ret = btrfs_get_bdev_and_sb(device->name->str, flags, holder, 1, |
641 | if (IS_ERR(bdev)) { | 679 | &bdev, &bh); |
642 | printk(KERN_INFO "btrfs: open %s failed\n", device->name->str); | 680 | if (ret) |
643 | goto error; | 681 | continue; |
644 | } | ||
645 | filemap_write_and_wait(bdev->bd_inode->i_mapping); | ||
646 | invalidate_bdev(bdev); | ||
647 | set_blocksize(bdev, 4096); | ||
648 | |||
649 | bh = btrfs_read_dev_super(bdev); | ||
650 | if (!bh) | ||
651 | goto error_close; | ||
652 | 682 | ||
653 | disk_super = (struct btrfs_super_block *)bh->b_data; | 683 | disk_super = (struct btrfs_super_block *)bh->b_data; |
654 | devid = btrfs_stack_device_id(&disk_super->dev_item); | 684 | devid = btrfs_stack_device_id(&disk_super->dev_item); |
@@ -697,9 +727,7 @@ static int __btrfs_open_devices(struct btrfs_fs_devices *fs_devices, | |||
697 | 727 | ||
698 | error_brelse: | 728 | error_brelse: |
699 | brelse(bh); | 729 | brelse(bh); |
700 | error_close: | ||
701 | blkdev_put(bdev, flags); | 730 | blkdev_put(bdev, flags); |
702 | error: | ||
703 | continue; | 731 | continue; |
704 | } | 732 | } |
705 | if (fs_devices->open_devices == 0) { | 733 | if (fs_devices->open_devices == 0) { |
@@ -744,22 +772,10 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder, | |||
744 | u64 total_devices; | 772 | u64 total_devices; |
745 | 773 | ||
746 | flags |= FMODE_EXCL; | 774 | flags |= FMODE_EXCL; |
747 | bdev = blkdev_get_by_path(path, flags, holder); | ||
748 | |||
749 | if (IS_ERR(bdev)) { | ||
750 | ret = PTR_ERR(bdev); | ||
751 | goto error; | ||
752 | } | ||
753 | |||
754 | mutex_lock(&uuid_mutex); | 775 | mutex_lock(&uuid_mutex); |
755 | ret = set_blocksize(bdev, 4096); | 776 | ret = btrfs_get_bdev_and_sb(path, flags, holder, 0, &bdev, &bh); |
756 | if (ret) | 777 | if (ret) |
757 | goto error_close; | 778 | goto error; |
758 | bh = btrfs_read_dev_super(bdev); | ||
759 | if (!bh) { | ||
760 | ret = -EINVAL; | ||
761 | goto error_close; | ||
762 | } | ||
763 | disk_super = (struct btrfs_super_block *)bh->b_data; | 779 | disk_super = (struct btrfs_super_block *)bh->b_data; |
764 | devid = btrfs_stack_device_id(&disk_super->dev_item); | 780 | devid = btrfs_stack_device_id(&disk_super->dev_item); |
765 | transid = btrfs_super_generation(disk_super); | 781 | transid = btrfs_super_generation(disk_super); |
@@ -777,10 +793,9 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder, | |||
777 | if (!ret && fs_devices_ret) | 793 | if (!ret && fs_devices_ret) |
778 | (*fs_devices_ret)->total_devices = total_devices; | 794 | (*fs_devices_ret)->total_devices = total_devices; |
779 | brelse(bh); | 795 | brelse(bh); |
780 | error_close: | ||
781 | mutex_unlock(&uuid_mutex); | ||
782 | blkdev_put(bdev, flags); | 796 | blkdev_put(bdev, flags); |
783 | error: | 797 | error: |
798 | mutex_unlock(&uuid_mutex); | ||
784 | return ret; | 799 | return ret; |
785 | } | 800 | } |
786 | 801 | ||
@@ -1374,20 +1389,12 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) | |||
1374 | goto out; | 1389 | goto out; |
1375 | } | 1390 | } |
1376 | } else { | 1391 | } else { |
1377 | bdev = blkdev_get_by_path(device_path, FMODE_READ | FMODE_EXCL, | 1392 | ret = btrfs_get_bdev_and_sb(device_path, |
1378 | root->fs_info->bdev_holder); | 1393 | FMODE_READ | FMODE_EXCL, |
1379 | if (IS_ERR(bdev)) { | 1394 | root->fs_info->bdev_holder, 0, |
1380 | ret = PTR_ERR(bdev); | 1395 | &bdev, &bh); |
1396 | if (ret) | ||
1381 | goto out; | 1397 | goto out; |
1382 | } | ||
1383 | |||
1384 | set_blocksize(bdev, 4096); | ||
1385 | invalidate_bdev(bdev); | ||
1386 | bh = btrfs_read_dev_super(bdev); | ||
1387 | if (!bh) { | ||
1388 | ret = -EINVAL; | ||
1389 | goto error_close; | ||
1390 | } | ||
1391 | disk_super = (struct btrfs_super_block *)bh->b_data; | 1398 | disk_super = (struct btrfs_super_block *)bh->b_data; |
1392 | devid = btrfs_stack_device_id(&disk_super->dev_item); | 1399 | devid = btrfs_stack_device_id(&disk_super->dev_item); |
1393 | dev_uuid = disk_super->dev_item.uuid; | 1400 | dev_uuid = disk_super->dev_item.uuid; |