Merge branch 'linux-kernel-disk' into refs/top-bases/linux-zfs-branch

This commit is contained in:
Brian Behlendorf 2010-08-04 16:10:44 -07:00
commit 5222cdac37
1 changed files with 36 additions and 9 deletions

View File

@ -815,9 +815,19 @@ static int
zvol_open(struct block_device *bdev, fmode_t flag) zvol_open(struct block_device *bdev, fmode_t flag)
{ {
zvol_state_t *zv = bdev->bd_disk->private_data; zvol_state_t *zv = bdev->bd_disk->private_data;
int error = 0; int error = 0, drop_mutex = 0;
/*
* If the caller is already holding the mutex do not take it
* again, this will happen as part of zvol_create_minor().
* Once add_disk() is called the device is live and the kernel
* will attempt to open it to read the partition information.
*/
if (!mutex_owned(&zvol_state_lock)) {
mutex_enter(&zvol_state_lock);
drop_mutex = 1;
}
mutex_enter(&zvol_state_lock);
ASSERT3P(zv, !=, NULL); ASSERT3P(zv, !=, NULL);
if (zv->zv_open_count == 0) { if (zv->zv_open_count == 0) {
@ -839,7 +849,8 @@ out_open_count:
zvol_last_close(zv); zvol_last_close(zv);
out_mutex: out_mutex:
mutex_exit(&zvol_state_lock); if (drop_mutex)
mutex_exit(&zvol_state_lock);
check_disk_change(bdev); check_disk_change(bdev);
@ -850,15 +861,21 @@ static int
zvol_release(struct gendisk *disk, fmode_t mode) zvol_release(struct gendisk *disk, fmode_t mode)
{ {
zvol_state_t *zv = disk->private_data; zvol_state_t *zv = disk->private_data;
int drop_mutex = 0;
if (!mutex_owned(&zvol_state_lock)) {
mutex_enter(&zvol_state_lock);
drop_mutex = 1;
}
mutex_enter(&zvol_state_lock);
ASSERT3P(zv, !=, NULL); ASSERT3P(zv, !=, NULL);
ASSERT3U(zv->zv_open_count, >, 0); ASSERT3U(zv->zv_open_count, >, 0);
zv->zv_open_count--; zv->zv_open_count--;
if (zv->zv_open_count == 0) if (zv->zv_open_count == 0)
zvol_last_close(zv); zvol_last_close(zv);
mutex_exit(&zvol_state_lock); if (drop_mutex)
mutex_exit(&zvol_state_lock);
return (0); return (0);
} }
@ -1083,6 +1100,7 @@ __zvol_create_minor(const char *name)
zvol_state_t *zv; zvol_state_t *zv;
objset_t *os; objset_t *os;
dmu_object_info_t *doi; dmu_object_info_t *doi;
uint64_t volsize;
unsigned minor = 0; unsigned minor = 0;
int error = 0; int error = 0;
@ -1104,6 +1122,10 @@ __zvol_create_minor(const char *name)
if (error) if (error)
goto out_dmu_objset_disown; goto out_dmu_objset_disown;
error = zap_lookup(os, ZVOL_ZAP_OBJ, "size", 8, 1, &volsize);
if (error)
goto out_dmu_objset_disown;
error = zvol_find_minor(&minor); error = zvol_find_minor(&minor);
if (error) if (error)
goto out_dmu_objset_disown; goto out_dmu_objset_disown;
@ -1118,23 +1140,28 @@ __zvol_create_minor(const char *name)
zv->zv_flags |= ZVOL_RDONLY; zv->zv_flags |= ZVOL_RDONLY;
zv->zv_volblocksize = doi->doi_data_block_size; zv->zv_volblocksize = doi->doi_data_block_size;
zv->zv_volsize = volsize;
zv->zv_objset = os; zv->zv_objset = os;
set_capacity(zv->zv_disk, zv->zv_volsize >> 9);
if (zil_replay_disable) if (zil_replay_disable)
zil_destroy(dmu_objset_zil(os), B_FALSE); zil_destroy(dmu_objset_zil(os), B_FALSE);
else else
zil_replay(os, zv, zvol_replay_vector); zil_replay(os, zv, zvol_replay_vector);
zvol_insert(zv);
add_disk(zv->zv_disk);
error = 0;
out_dmu_objset_disown: out_dmu_objset_disown:
dmu_objset_disown(os, zvol_tag); dmu_objset_disown(os, zvol_tag);
zv->zv_objset = NULL; zv->zv_objset = NULL;
out_doi: out_doi:
kmem_free(doi, sizeof(dmu_object_info_t)); kmem_free(doi, sizeof(dmu_object_info_t));
out: out:
if (error == 0) {
zvol_insert(zv);
add_disk(zv->zv_disk);
}
return (error); return (error);
} }