aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/volumes.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-05-13 16:03:06 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:03 -0400
commita0af469b58944f6e8c5c8ecbebb42997baf0cb9e (patch)
tree1fa478aa49c24d60417a2e1239050c4c1435a0dc /fs/btrfs/volumes.c
parentdfe25020689bb2d318782d2c9c7141203583fc70 (diff)
Fix btrfs_open_devices to deal with changes since the scan ioctls
Devices can change after the scan ioctls are done, and btrfs_open_devices needs to be able to verify them as they are opened and used by the FS. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r--fs/btrfs/volumes.c70
1 files changed, 59 insertions, 11 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 43f74d17bcea..501d23d3ebfd 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -71,6 +71,7 @@ int btrfs_cleanup_fs_uuids(void)
71 dev_list); 71 dev_list);
72 if (dev->bdev) { 72 if (dev->bdev) {
73 close_bdev_excl(dev->bdev); 73 close_bdev_excl(dev->bdev);
74 fs_devices->open_devices--;
74 } 75 }
75 list_del(&dev->dev_list); 76 list_del(&dev->dev_list);
76 kfree(dev->name); 77 kfree(dev->name);
@@ -174,9 +175,10 @@ again:
174 list_for_each(cur, head) { 175 list_for_each(cur, head) {
175 device = list_entry(cur, struct btrfs_device, dev_list); 176 device = list_entry(cur, struct btrfs_device, dev_list);
176 if (!device->in_fs_metadata) { 177 if (!device->in_fs_metadata) {
177printk("getting rid of extra dev %s\n", device->name); 178 if (device->bdev) {
178 if (device->bdev)
179 close_bdev_excl(device->bdev); 179 close_bdev_excl(device->bdev);
180 fs_devices->open_devices--;
181 }
180 list_del(&device->dev_list); 182 list_del(&device->dev_list);
181 list_del(&device->dev_alloc_list); 183 list_del(&device->dev_alloc_list);
182 fs_devices->num_devices--; 184 fs_devices->num_devices--;
@@ -188,6 +190,7 @@ printk("getting rid of extra dev %s\n", device->name);
188 mutex_unlock(&uuid_mutex); 190 mutex_unlock(&uuid_mutex);
189 return 0; 191 return 0;
190} 192}
193
191int btrfs_close_devices(struct btrfs_fs_devices *fs_devices) 194int btrfs_close_devices(struct btrfs_fs_devices *fs_devices)
192{ 195{
193 struct list_head *head = &fs_devices->devices; 196 struct list_head *head = &fs_devices->devices;
@@ -199,10 +202,12 @@ int btrfs_close_devices(struct btrfs_fs_devices *fs_devices)
199 device = list_entry(cur, struct btrfs_device, dev_list); 202 device = list_entry(cur, struct btrfs_device, dev_list);
200 if (device->bdev) { 203 if (device->bdev) {
201 close_bdev_excl(device->bdev); 204 close_bdev_excl(device->bdev);
205 fs_devices->open_devices--;
202 } 206 }
203 device->bdev = NULL; 207 device->bdev = NULL;
204 device->in_fs_metadata = 0; 208 device->in_fs_metadata = 0;
205 } 209 }
210 fs_devices->mounted = 0;
206 mutex_unlock(&uuid_mutex); 211 mutex_unlock(&uuid_mutex);
207 return 0; 212 return 0;
208} 213}
@@ -214,9 +219,19 @@ int btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
214 struct list_head *head = &fs_devices->devices; 219 struct list_head *head = &fs_devices->devices;
215 struct list_head *cur; 220 struct list_head *cur;
216 struct btrfs_device *device; 221 struct btrfs_device *device;
217 int ret; 222 struct block_device *latest_bdev = NULL;
223 struct buffer_head *bh;
224 struct btrfs_super_block *disk_super;
225 u64 latest_devid = 0;
226 u64 latest_transid = 0;
227 u64 transid;
228 u64 devid;
229 int ret = 0;
218 230
219 mutex_lock(&uuid_mutex); 231 mutex_lock(&uuid_mutex);
232 if (fs_devices->mounted)
233 goto out;
234
220 list_for_each(cur, head) { 235 list_for_each(cur, head) {
221 device = list_entry(cur, struct btrfs_device, dev_list); 236 device = list_entry(cur, struct btrfs_device, dev_list);
222 if (device->bdev) 237 if (device->bdev)
@@ -229,21 +244,52 @@ int btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
229 244
230 if (IS_ERR(bdev)) { 245 if (IS_ERR(bdev)) {
231 printk("open %s failed\n", device->name); 246 printk("open %s failed\n", device->name);
232 ret = PTR_ERR(bdev); 247 goto error;
233 goto fail;
234 } 248 }
235 set_blocksize(bdev, 4096); 249 set_blocksize(bdev, 4096);
236 if (device->devid == fs_devices->latest_devid) 250
237 fs_devices->latest_bdev = bdev; 251 bh = __bread(bdev, BTRFS_SUPER_INFO_OFFSET / 4096, 4096);
252 if (!bh)
253 goto error_close;
254
255 disk_super = (struct btrfs_super_block *)bh->b_data;
256 if (strncmp((char *)(&disk_super->magic), BTRFS_MAGIC,
257 sizeof(disk_super->magic)))
258 goto error_brelse;
259
260 devid = le64_to_cpu(disk_super->dev_item.devid);
261 if (devid != device->devid)
262 goto error_brelse;
263
264 transid = btrfs_super_generation(disk_super);
265 if (transid > latest_transid) {
266 latest_devid = devid;
267 latest_transid = transid;
268 latest_bdev = bdev;
269 }
270
238 device->bdev = bdev; 271 device->bdev = bdev;
239 device->in_fs_metadata = 0; 272 device->in_fs_metadata = 0;
273 fs_devices->open_devices++;
274 continue;
240 275
276error_brelse:
277 brelse(bh);
278error_close:
279 close_bdev_excl(bdev);
280error:
281 continue;
241 } 282 }
283 if (fs_devices->open_devices == 0) {
284 ret = -EIO;
285 goto out;
286 }
287 fs_devices->mounted = 1;
288 fs_devices->latest_bdev = latest_bdev;
289 fs_devices->latest_devid = latest_devid;
290 fs_devices->latest_trans = latest_transid;
291out:
242 mutex_unlock(&uuid_mutex); 292 mutex_unlock(&uuid_mutex);
243 return 0;
244fail:
245 mutex_unlock(&uuid_mutex);
246 btrfs_close_devices(fs_devices);
247 return ret; 293 return ret;
248} 294}
249 295
@@ -828,6 +874,7 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
828 if (device->bdev) { 874 if (device->bdev) {
829 /* one close for the device struct or super_block */ 875 /* one close for the device struct or super_block */
830 close_bdev_excl(device->bdev); 876 close_bdev_excl(device->bdev);
877 root->fs_info->fs_devices->open_devices--;
831 } 878 }
832 if (bdev) { 879 if (bdev) {
833 /* one close for us */ 880 /* one close for us */
@@ -914,6 +961,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
914 list_add(&device->dev_alloc_list, 961 list_add(&device->dev_alloc_list,
915 &root->fs_info->fs_devices->alloc_list); 962 &root->fs_info->fs_devices->alloc_list);
916 root->fs_info->fs_devices->num_devices++; 963 root->fs_info->fs_devices->num_devices++;
964 root->fs_info->fs_devices->open_devices++;
917out: 965out:
918 btrfs_end_transaction(trans, root); 966 btrfs_end_transaction(trans, root);
919 mutex_unlock(&root->fs_info->fs_mutex); 967 mutex_unlock(&root->fs_info->fs_mutex);