diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/block/rbd.c | 72 |
1 files changed, 29 insertions, 43 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 013c7a549fb6..65665c9c42c6 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c | |||
@@ -141,7 +141,7 @@ struct rbd_request { | |||
141 | struct rbd_snap { | 141 | struct rbd_snap { |
142 | struct device dev; | 142 | struct device dev; |
143 | const char *name; | 143 | const char *name; |
144 | size_t size; | 144 | u64 size; |
145 | struct list_head node; | 145 | struct list_head node; |
146 | u64 id; | 146 | u64 id; |
147 | }; | 147 | }; |
@@ -175,8 +175,7 @@ struct rbd_device { | |||
175 | /* protects updating the header */ | 175 | /* protects updating the header */ |
176 | struct rw_semaphore header_rwsem; | 176 | struct rw_semaphore header_rwsem; |
177 | char snap_name[RBD_MAX_SNAP_NAME_LEN]; | 177 | char snap_name[RBD_MAX_SNAP_NAME_LEN]; |
178 | u32 cur_snap; /* index+1 of current snapshot within snap context | 178 | u64 snap_id; /* current snapshot id */ |
179 | 0 - for the head */ | ||
180 | int read_only; | 179 | int read_only; |
181 | 180 | ||
182 | struct list_head node; | 181 | struct list_head node; |
@@ -241,7 +240,7 @@ static void rbd_put_dev(struct rbd_device *rbd_dev) | |||
241 | put_device(&rbd_dev->dev); | 240 | put_device(&rbd_dev->dev); |
242 | } | 241 | } |
243 | 242 | ||
244 | static int __rbd_update_snaps(struct rbd_device *rbd_dev); | 243 | static int __rbd_refresh_header(struct rbd_device *rbd_dev); |
245 | 244 | ||
246 | static int rbd_open(struct block_device *bdev, fmode_t mode) | 245 | static int rbd_open(struct block_device *bdev, fmode_t mode) |
247 | { | 246 | { |
@@ -450,7 +449,9 @@ static void rbd_client_release(struct kref *kref) | |||
450 | struct rbd_client *rbdc = container_of(kref, struct rbd_client, kref); | 449 | struct rbd_client *rbdc = container_of(kref, struct rbd_client, kref); |
451 | 450 | ||
452 | dout("rbd_release_client %p\n", rbdc); | 451 | dout("rbd_release_client %p\n", rbdc); |
452 | spin_lock(&rbd_client_list_lock); | ||
453 | list_del(&rbdc->node); | 453 | list_del(&rbdc->node); |
454 | spin_unlock(&rbd_client_list_lock); | ||
454 | 455 | ||
455 | ceph_destroy_client(rbdc->client); | 456 | ceph_destroy_client(rbdc->client); |
456 | kfree(rbdc->rbd_opts); | 457 | kfree(rbdc->rbd_opts); |
@@ -463,9 +464,7 @@ static void rbd_client_release(struct kref *kref) | |||
463 | */ | 464 | */ |
464 | static void rbd_put_client(struct rbd_device *rbd_dev) | 465 | static void rbd_put_client(struct rbd_device *rbd_dev) |
465 | { | 466 | { |
466 | spin_lock(&rbd_client_list_lock); | ||
467 | kref_put(&rbd_dev->rbd_client->kref, rbd_client_release); | 467 | kref_put(&rbd_dev->rbd_client->kref, rbd_client_release); |
468 | spin_unlock(&rbd_client_list_lock); | ||
469 | rbd_dev->rbd_client = NULL; | 468 | rbd_dev->rbd_client = NULL; |
470 | } | 469 | } |
471 | 470 | ||
@@ -487,16 +486,18 @@ static void rbd_coll_release(struct kref *kref) | |||
487 | */ | 486 | */ |
488 | static int rbd_header_from_disk(struct rbd_image_header *header, | 487 | static int rbd_header_from_disk(struct rbd_image_header *header, |
489 | struct rbd_image_header_ondisk *ondisk, | 488 | struct rbd_image_header_ondisk *ondisk, |
490 | int allocated_snaps, | 489 | u32 allocated_snaps, |
491 | gfp_t gfp_flags) | 490 | gfp_t gfp_flags) |
492 | { | 491 | { |
493 | int i; | 492 | u32 i, snap_count; |
494 | u32 snap_count; | ||
495 | 493 | ||
496 | if (memcmp(ondisk, RBD_HEADER_TEXT, sizeof(RBD_HEADER_TEXT))) | 494 | if (memcmp(ondisk, RBD_HEADER_TEXT, sizeof(RBD_HEADER_TEXT))) |
497 | return -ENXIO; | 495 | return -ENXIO; |
498 | 496 | ||
499 | snap_count = le32_to_cpu(ondisk->snap_count); | 497 | snap_count = le32_to_cpu(ondisk->snap_count); |
498 | if (snap_count > (UINT_MAX - sizeof(struct ceph_snap_context)) | ||
499 | / sizeof (*ondisk)) | ||
500 | return -EINVAL; | ||
500 | header->snapc = kmalloc(sizeof(struct ceph_snap_context) + | 501 | header->snapc = kmalloc(sizeof(struct ceph_snap_context) + |
501 | snap_count * sizeof (*ondisk), | 502 | snap_count * sizeof (*ondisk), |
502 | gfp_flags); | 503 | gfp_flags); |
@@ -506,11 +507,11 @@ static int rbd_header_from_disk(struct rbd_image_header *header, | |||
506 | header->snap_names_len = le64_to_cpu(ondisk->snap_names_len); | 507 | header->snap_names_len = le64_to_cpu(ondisk->snap_names_len); |
507 | if (snap_count) { | 508 | if (snap_count) { |
508 | header->snap_names = kmalloc(header->snap_names_len, | 509 | header->snap_names = kmalloc(header->snap_names_len, |
509 | GFP_KERNEL); | 510 | gfp_flags); |
510 | if (!header->snap_names) | 511 | if (!header->snap_names) |
511 | goto err_snapc; | 512 | goto err_snapc; |
512 | header->snap_sizes = kmalloc(snap_count * sizeof(u64), | 513 | header->snap_sizes = kmalloc(snap_count * sizeof(u64), |
513 | GFP_KERNEL); | 514 | gfp_flags); |
514 | if (!header->snap_sizes) | 515 | if (!header->snap_sizes) |
515 | goto err_names; | 516 | goto err_names; |
516 | } else { | 517 | } else { |
@@ -552,21 +553,6 @@ err_snapc: | |||
552 | return -ENOMEM; | 553 | return -ENOMEM; |
553 | } | 554 | } |
554 | 555 | ||
555 | static int snap_index(struct rbd_image_header *header, int snap_num) | ||
556 | { | ||
557 | return header->total_snaps - snap_num; | ||
558 | } | ||
559 | |||
560 | static u64 cur_snap_id(struct rbd_device *rbd_dev) | ||
561 | { | ||
562 | struct rbd_image_header *header = &rbd_dev->header; | ||
563 | |||
564 | if (!rbd_dev->cur_snap) | ||
565 | return 0; | ||
566 | |||
567 | return header->snapc->snaps[snap_index(header, rbd_dev->cur_snap)]; | ||
568 | } | ||
569 | |||
570 | static int snap_by_name(struct rbd_image_header *header, const char *snap_name, | 556 | static int snap_by_name(struct rbd_image_header *header, const char *snap_name, |
571 | u64 *seq, u64 *size) | 557 | u64 *seq, u64 *size) |
572 | { | 558 | { |
@@ -605,7 +591,7 @@ static int rbd_header_set_snap(struct rbd_device *dev, u64 *size) | |||
605 | snapc->seq = header->snap_seq; | 591 | snapc->seq = header->snap_seq; |
606 | else | 592 | else |
607 | snapc->seq = 0; | 593 | snapc->seq = 0; |
608 | dev->cur_snap = 0; | 594 | dev->snap_id = CEPH_NOSNAP; |
609 | dev->read_only = 0; | 595 | dev->read_only = 0; |
610 | if (size) | 596 | if (size) |
611 | *size = header->image_size; | 597 | *size = header->image_size; |
@@ -613,8 +599,7 @@ static int rbd_header_set_snap(struct rbd_device *dev, u64 *size) | |||
613 | ret = snap_by_name(header, dev->snap_name, &snapc->seq, size); | 599 | ret = snap_by_name(header, dev->snap_name, &snapc->seq, size); |
614 | if (ret < 0) | 600 | if (ret < 0) |
615 | goto done; | 601 | goto done; |
616 | 602 | dev->snap_id = snapc->seq; | |
617 | dev->cur_snap = header->total_snaps - ret; | ||
618 | dev->read_only = 1; | 603 | dev->read_only = 1; |
619 | } | 604 | } |
620 | 605 | ||
@@ -935,7 +920,6 @@ static int rbd_do_request(struct request *rq, | |||
935 | layout->fl_stripe_unit = cpu_to_le32(1 << RBD_MAX_OBJ_ORDER); | 920 | layout->fl_stripe_unit = cpu_to_le32(1 << RBD_MAX_OBJ_ORDER); |
936 | layout->fl_stripe_count = cpu_to_le32(1); | 921 | layout->fl_stripe_count = cpu_to_le32(1); |
937 | layout->fl_object_size = cpu_to_le32(1 << RBD_MAX_OBJ_ORDER); | 922 | layout->fl_object_size = cpu_to_le32(1 << RBD_MAX_OBJ_ORDER); |
938 | layout->fl_pg_preferred = cpu_to_le32(-1); | ||
939 | layout->fl_pg_pool = cpu_to_le32(dev->poolid); | 923 | layout->fl_pg_pool = cpu_to_le32(dev->poolid); |
940 | ceph_calc_raw_layout(osdc, layout, snapid, ofs, &len, &bno, | 924 | ceph_calc_raw_layout(osdc, layout, snapid, ofs, &len, &bno, |
941 | req, ops); | 925 | req, ops); |
@@ -1168,7 +1152,7 @@ static int rbd_req_read(struct request *rq, | |||
1168 | int coll_index) | 1152 | int coll_index) |
1169 | { | 1153 | { |
1170 | return rbd_do_op(rq, rbd_dev, NULL, | 1154 | return rbd_do_op(rq, rbd_dev, NULL, |
1171 | (snapid ? snapid : CEPH_NOSNAP), | 1155 | snapid, |
1172 | CEPH_OSD_OP_READ, | 1156 | CEPH_OSD_OP_READ, |
1173 | CEPH_OSD_FLAG_READ, | 1157 | CEPH_OSD_FLAG_READ, |
1174 | 2, | 1158 | 2, |
@@ -1187,7 +1171,7 @@ static int rbd_req_sync_read(struct rbd_device *dev, | |||
1187 | u64 *ver) | 1171 | u64 *ver) |
1188 | { | 1172 | { |
1189 | return rbd_req_sync_op(dev, NULL, | 1173 | return rbd_req_sync_op(dev, NULL, |
1190 | (snapid ? snapid : CEPH_NOSNAP), | 1174 | snapid, |
1191 | CEPH_OSD_OP_READ, | 1175 | CEPH_OSD_OP_READ, |
1192 | CEPH_OSD_FLAG_READ, | 1176 | CEPH_OSD_FLAG_READ, |
1193 | NULL, | 1177 | NULL, |
@@ -1238,7 +1222,7 @@ static void rbd_watch_cb(u64 ver, u64 notify_id, u8 opcode, void *data) | |||
1238 | dout("rbd_watch_cb %s notify_id=%lld opcode=%d\n", dev->obj_md_name, | 1222 | dout("rbd_watch_cb %s notify_id=%lld opcode=%d\n", dev->obj_md_name, |
1239 | notify_id, (int)opcode); | 1223 | notify_id, (int)opcode); |
1240 | mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); | 1224 | mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); |
1241 | rc = __rbd_update_snaps(dev); | 1225 | rc = __rbd_refresh_header(dev); |
1242 | mutex_unlock(&ctl_mutex); | 1226 | mutex_unlock(&ctl_mutex); |
1243 | if (rc) | 1227 | if (rc) |
1244 | pr_warning(RBD_DRV_NAME "%d got notification but failed to " | 1228 | pr_warning(RBD_DRV_NAME "%d got notification but failed to " |
@@ -1521,7 +1505,7 @@ static void rbd_rq_fn(struct request_queue *q) | |||
1521 | coll, cur_seg); | 1505 | coll, cur_seg); |
1522 | else | 1506 | else |
1523 | rbd_req_read(rq, rbd_dev, | 1507 | rbd_req_read(rq, rbd_dev, |
1524 | cur_snap_id(rbd_dev), | 1508 | rbd_dev->snap_id, |
1525 | ofs, | 1509 | ofs, |
1526 | op_size, bio, | 1510 | op_size, bio, |
1527 | coll, cur_seg); | 1511 | coll, cur_seg); |
@@ -1592,7 +1576,7 @@ static int rbd_read_header(struct rbd_device *rbd_dev, | |||
1592 | { | 1576 | { |
1593 | ssize_t rc; | 1577 | ssize_t rc; |
1594 | struct rbd_image_header_ondisk *dh; | 1578 | struct rbd_image_header_ondisk *dh; |
1595 | int snap_count = 0; | 1579 | u32 snap_count = 0; |
1596 | u64 ver; | 1580 | u64 ver; |
1597 | size_t len; | 1581 | size_t len; |
1598 | 1582 | ||
@@ -1656,7 +1640,7 @@ static int rbd_header_add_snap(struct rbd_device *dev, | |||
1656 | struct ceph_mon_client *monc; | 1640 | struct ceph_mon_client *monc; |
1657 | 1641 | ||
1658 | /* we should create a snapshot only if we're pointing at the head */ | 1642 | /* we should create a snapshot only if we're pointing at the head */ |
1659 | if (dev->cur_snap) | 1643 | if (dev->snap_id != CEPH_NOSNAP) |
1660 | return -EINVAL; | 1644 | return -EINVAL; |
1661 | 1645 | ||
1662 | monc = &dev->rbd_client->client->monc; | 1646 | monc = &dev->rbd_client->client->monc; |
@@ -1683,7 +1667,9 @@ static int rbd_header_add_snap(struct rbd_device *dev, | |||
1683 | if (ret < 0) | 1667 | if (ret < 0) |
1684 | return ret; | 1668 | return ret; |
1685 | 1669 | ||
1686 | dev->header.snapc->seq = new_snapid; | 1670 | down_write(&dev->header_rwsem); |
1671 | dev->header.snapc->seq = new_snapid; | ||
1672 | up_write(&dev->header_rwsem); | ||
1687 | 1673 | ||
1688 | return 0; | 1674 | return 0; |
1689 | bad: | 1675 | bad: |
@@ -1703,7 +1689,7 @@ static void __rbd_remove_all_snaps(struct rbd_device *rbd_dev) | |||
1703 | /* | 1689 | /* |
1704 | * only read the first part of the ondisk header, without the snaps info | 1690 | * only read the first part of the ondisk header, without the snaps info |
1705 | */ | 1691 | */ |
1706 | static int __rbd_update_snaps(struct rbd_device *rbd_dev) | 1692 | static int __rbd_refresh_header(struct rbd_device *rbd_dev) |
1707 | { | 1693 | { |
1708 | int ret; | 1694 | int ret; |
1709 | struct rbd_image_header h; | 1695 | struct rbd_image_header h; |
@@ -1890,7 +1876,7 @@ static ssize_t rbd_image_refresh(struct device *dev, | |||
1890 | 1876 | ||
1891 | mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); | 1877 | mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); |
1892 | 1878 | ||
1893 | rc = __rbd_update_snaps(rbd_dev); | 1879 | rc = __rbd_refresh_header(rbd_dev); |
1894 | if (rc < 0) | 1880 | if (rc < 0) |
1895 | ret = rc; | 1881 | ret = rc; |
1896 | 1882 | ||
@@ -1949,7 +1935,7 @@ static ssize_t rbd_snap_size_show(struct device *dev, | |||
1949 | { | 1935 | { |
1950 | struct rbd_snap *snap = container_of(dev, struct rbd_snap, dev); | 1936 | struct rbd_snap *snap = container_of(dev, struct rbd_snap, dev); |
1951 | 1937 | ||
1952 | return sprintf(buf, "%zd\n", snap->size); | 1938 | return sprintf(buf, "%llu\n", (unsigned long long)snap->size); |
1953 | } | 1939 | } |
1954 | 1940 | ||
1955 | static ssize_t rbd_snap_id_show(struct device *dev, | 1941 | static ssize_t rbd_snap_id_show(struct device *dev, |
@@ -1958,7 +1944,7 @@ static ssize_t rbd_snap_id_show(struct device *dev, | |||
1958 | { | 1944 | { |
1959 | struct rbd_snap *snap = container_of(dev, struct rbd_snap, dev); | 1945 | struct rbd_snap *snap = container_of(dev, struct rbd_snap, dev); |
1960 | 1946 | ||
1961 | return sprintf(buf, "%llu\n", (unsigned long long) snap->id); | 1947 | return sprintf(buf, "%llu\n", (unsigned long long)snap->id); |
1962 | } | 1948 | } |
1963 | 1949 | ||
1964 | static DEVICE_ATTR(snap_size, S_IRUGO, rbd_snap_size_show, NULL); | 1950 | static DEVICE_ATTR(snap_size, S_IRUGO, rbd_snap_size_show, NULL); |
@@ -2173,7 +2159,7 @@ static int rbd_init_watch_dev(struct rbd_device *rbd_dev) | |||
2173 | rbd_dev->header.obj_version); | 2159 | rbd_dev->header.obj_version); |
2174 | if (ret == -ERANGE) { | 2160 | if (ret == -ERANGE) { |
2175 | mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); | 2161 | mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); |
2176 | rc = __rbd_update_snaps(rbd_dev); | 2162 | rc = __rbd_refresh_header(rbd_dev); |
2177 | mutex_unlock(&ctl_mutex); | 2163 | mutex_unlock(&ctl_mutex); |
2178 | if (rc < 0) | 2164 | if (rc < 0) |
2179 | return rc; | 2165 | return rc; |
@@ -2558,7 +2544,7 @@ static ssize_t rbd_snap_add(struct device *dev, | |||
2558 | if (ret < 0) | 2544 | if (ret < 0) |
2559 | goto err_unlock; | 2545 | goto err_unlock; |
2560 | 2546 | ||
2561 | ret = __rbd_update_snaps(rbd_dev); | 2547 | ret = __rbd_refresh_header(rbd_dev); |
2562 | if (ret < 0) | 2548 | if (ret < 0) |
2563 | goto err_unlock; | 2549 | goto err_unlock; |
2564 | 2550 | ||