aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/rbd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/block/rbd.c')
-rw-r--r--drivers/block/rbd.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 1222d583ac2c..34676937d2d2 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -494,14 +494,14 @@ static int rbd_header_from_disk(struct rbd_image_header *header,
494 struct rbd_image_header_ondisk *ondisk, 494 struct rbd_image_header_ondisk *ondisk,
495 u32 allocated_snaps) 495 u32 allocated_snaps)
496{ 496{
497 u32 i, snap_count; 497 u32 snap_count;
498 498
499 if (!rbd_dev_ondisk_valid(ondisk)) 499 if (!rbd_dev_ondisk_valid(ondisk))
500 return -ENXIO; 500 return -ENXIO;
501 501
502 snap_count = le32_to_cpu(ondisk->snap_count); 502 snap_count = le32_to_cpu(ondisk->snap_count);
503 if (snap_count > (UINT_MAX - sizeof(struct ceph_snap_context)) 503 if (snap_count > (SIZE_MAX - sizeof(struct ceph_snap_context))
504 / sizeof (*ondisk)) 504 / sizeof (u64))
505 return -EINVAL; 505 return -EINVAL;
506 header->snapc = kmalloc(sizeof(struct ceph_snap_context) + 506 header->snapc = kmalloc(sizeof(struct ceph_snap_context) +
507 snap_count * sizeof(u64), 507 snap_count * sizeof(u64),
@@ -509,8 +509,8 @@ static int rbd_header_from_disk(struct rbd_image_header *header,
509 if (!header->snapc) 509 if (!header->snapc)
510 return -ENOMEM; 510 return -ENOMEM;
511 511
512 header->snap_names_len = le64_to_cpu(ondisk->snap_names_len);
513 if (snap_count) { 512 if (snap_count) {
513 header->snap_names_len = le64_to_cpu(ondisk->snap_names_len);
514 header->snap_names = kmalloc(header->snap_names_len, 514 header->snap_names = kmalloc(header->snap_names_len,
515 GFP_KERNEL); 515 GFP_KERNEL);
516 if (!header->snap_names) 516 if (!header->snap_names)
@@ -520,6 +520,8 @@ static int rbd_header_from_disk(struct rbd_image_header *header,
520 if (!header->snap_sizes) 520 if (!header->snap_sizes)
521 goto err_names; 521 goto err_names;
522 } else { 522 } else {
523 WARN_ON(ondisk->snap_names_len);
524 header->snap_names_len = 0;
523 header->snap_names = NULL; 525 header->snap_names = NULL;
524 header->snap_sizes = NULL; 526 header->snap_sizes = NULL;
525 } 527 }
@@ -544,6 +546,8 @@ static int rbd_header_from_disk(struct rbd_image_header *header,
544 header->total_snaps = snap_count; 546 header->total_snaps = snap_count;
545 547
546 if (snap_count && allocated_snaps == snap_count) { 548 if (snap_count && allocated_snaps == snap_count) {
549 int i;
550
547 for (i = 0; i < snap_count; i++) { 551 for (i = 0; i < snap_count; i++) {
548 header->snapc->snaps[i] = 552 header->snapc->snaps[i] =
549 le64_to_cpu(ondisk->snaps[i].id); 553 le64_to_cpu(ondisk->snaps[i].id);
@@ -552,7 +556,7 @@ static int rbd_header_from_disk(struct rbd_image_header *header,
552 } 556 }
553 557
554 /* copy snapshot names */ 558 /* copy snapshot names */
555 memcpy(header->snap_names, &ondisk->snaps[i], 559 memcpy(header->snap_names, &ondisk->snaps[snap_count],
556 header->snap_names_len); 560 header->snap_names_len);
557 } 561 }
558 562
@@ -560,10 +564,14 @@ static int rbd_header_from_disk(struct rbd_image_header *header,
560 564
561err_sizes: 565err_sizes:
562 kfree(header->snap_sizes); 566 kfree(header->snap_sizes);
567 header->snap_sizes = NULL;
563err_names: 568err_names:
564 kfree(header->snap_names); 569 kfree(header->snap_names);
570 header->snap_names = NULL;
565err_snapc: 571err_snapc:
566 kfree(header->snapc); 572 kfree(header->snapc);
573 header->snapc = NULL;
574
567 return -ENOMEM; 575 return -ENOMEM;
568} 576}
569 577