diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 2a94f8e81f67..c9de0f8e808e 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -506,11 +506,14 @@ static int rbd_header_from_disk(struct rbd_image_header *header, if (snap_count > size / sizeof (header->snapc->snaps[0])) return -EINVAL; - size = sizeof (struct ceph_snap_context); - size += snap_count * sizeof (header->snapc->snaps[0]); - header->snapc = kmalloc(size, GFP_KERNEL); - if (!header->snapc) + memset(header, 0, sizeof (*header)); + + size = sizeof (ondisk->block_name) + 1; + header->object_prefix = kmalloc(size, GFP_KERNEL); + if (!header->object_prefix) return -ENOMEM; + memcpy(header->object_prefix, ondisk->block_name, size - 1); + header->object_prefix[size - 1] = '\0'; if (snap_count) { header->snap_names_len = le64_to_cpu(ondisk->snap_names_len); @@ -518,11 +521,12 @@ static int rbd_header_from_disk(struct rbd_image_header *header, header->snap_names = kmalloc(header->snap_names_len, GFP_KERNEL); if (!header->snap_names) - goto err_snapc; + goto out_err; + size = snap_count * sizeof (*header->snap_sizes); header->snap_sizes = kmalloc(size, GFP_KERNEL); if (!header->snap_sizes) - goto err_names; + goto out_err; } else { WARN_ON(ondisk->snap_names_len); header->snap_names_len = 0; @@ -530,22 +534,23 @@ static int rbd_header_from_disk(struct rbd_image_header *header, header->snap_sizes = NULL; } - size = sizeof (ondisk->block_name) + 1; - header->object_prefix = kmalloc(size, GFP_KERNEL); - if (!header->object_prefix) - goto err_sizes; - memcpy(header->object_prefix, ondisk->block_name, size - 1); - header->object_prefix[size - 1] = '\0'; - header->image_size = le64_to_cpu(ondisk->image_size); header->obj_order = ondisk->options.order; header->crypt_type = ondisk->options.crypt_type; header->comp_type = ondisk->options.comp_type; + header->total_snaps = snap_count; + + /* Set up the snapshot context */ + + size = sizeof (struct ceph_snap_context); + size += snap_count * sizeof (header->snapc->snaps[0]); + header->snapc = kzalloc(size, GFP_KERNEL); + if (!header->snapc) + goto out_err; atomic_set(&header->snapc->nref, 1); header->snapc->seq = le64_to_cpu(ondisk->snap_seq); header->snapc->num_snaps = snap_count; - header->total_snaps = snap_count; if (snap_count && allocated_snaps == snap_count) { int i; @@ -564,16 +569,14 @@ static int rbd_header_from_disk(struct rbd_image_header *header, return 0; -err_sizes: +out_err: kfree(header->snap_sizes); header->snap_sizes = NULL; -err_names: kfree(header->snap_names); header->snap_names = NULL; header->snap_names_len = 0; -err_snapc: - kfree(header->snapc); - header->snapc = NULL; + kfree(header->object_prefix); + header->object_prefix = NULL; return -ENOMEM; }