diff options
-rw-r--r-- | drivers/block/rbd.c | 128 |
1 files changed, 62 insertions, 66 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 4cfe9f96589e..db29783436c8 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c | |||
@@ -1519,6 +1519,57 @@ static void rbd_img_request_destroy(struct kref *kref) | |||
1519 | kfree(img_request); | 1519 | kfree(img_request); |
1520 | } | 1520 | } |
1521 | 1521 | ||
1522 | static void rbd_img_obj_callback(struct rbd_obj_request *obj_request) | ||
1523 | { | ||
1524 | struct rbd_img_request *img_request; | ||
1525 | u32 which = obj_request->which; | ||
1526 | bool more = true; | ||
1527 | |||
1528 | img_request = obj_request->img_request; | ||
1529 | |||
1530 | dout("%s: img %p obj %p\n", __func__, img_request, obj_request); | ||
1531 | rbd_assert(img_request != NULL); | ||
1532 | rbd_assert(img_request->rq != NULL); | ||
1533 | rbd_assert(img_request->obj_request_count > 0); | ||
1534 | rbd_assert(which != BAD_WHICH); | ||
1535 | rbd_assert(which < img_request->obj_request_count); | ||
1536 | rbd_assert(which >= img_request->next_completion); | ||
1537 | |||
1538 | spin_lock_irq(&img_request->completion_lock); | ||
1539 | if (which != img_request->next_completion) | ||
1540 | goto out; | ||
1541 | |||
1542 | for_each_obj_request_from(img_request, obj_request) { | ||
1543 | unsigned int xferred; | ||
1544 | int result; | ||
1545 | |||
1546 | rbd_assert(more); | ||
1547 | rbd_assert(which < img_request->obj_request_count); | ||
1548 | |||
1549 | if (!obj_request_done_test(obj_request)) | ||
1550 | break; | ||
1551 | |||
1552 | rbd_assert(obj_request->xferred <= (u64) UINT_MAX); | ||
1553 | xferred = (unsigned int) obj_request->xferred; | ||
1554 | result = (int) obj_request->result; | ||
1555 | if (result) | ||
1556 | rbd_warn(NULL, "obj_request %s result %d xferred %u\n", | ||
1557 | img_request->write_request ? "write" : "read", | ||
1558 | result, xferred); | ||
1559 | |||
1560 | more = blk_end_request(img_request->rq, result, xferred); | ||
1561 | which++; | ||
1562 | } | ||
1563 | |||
1564 | rbd_assert(more ^ (which == img_request->obj_request_count)); | ||
1565 | img_request->next_completion = which; | ||
1566 | out: | ||
1567 | spin_unlock_irq(&img_request->completion_lock); | ||
1568 | |||
1569 | if (!more) | ||
1570 | rbd_img_request_complete(img_request); | ||
1571 | } | ||
1572 | |||
1522 | static int rbd_img_request_fill_bio(struct rbd_img_request *img_request, | 1573 | static int rbd_img_request_fill_bio(struct rbd_img_request *img_request, |
1523 | struct bio *bio_list) | 1574 | struct bio *bio_list) |
1524 | { | 1575 | { |
@@ -1572,6 +1623,7 @@ static int rbd_img_request_fill_bio(struct rbd_img_request *img_request, | |||
1572 | if (!osd_req) | 1623 | if (!osd_req) |
1573 | goto out_partial; | 1624 | goto out_partial; |
1574 | obj_request->osd_req = osd_req; | 1625 | obj_request->osd_req = osd_req; |
1626 | obj_request->callback = rbd_img_obj_callback; | ||
1575 | 1627 | ||
1576 | osd_data = write_request ? &osd_req->r_data_out | 1628 | osd_data = write_request ? &osd_req->r_data_out |
1577 | : &osd_req->r_data_in; | 1629 | : &osd_req->r_data_in; |
@@ -1582,8 +1634,6 @@ static int rbd_img_request_fill_bio(struct rbd_img_request *img_request, | |||
1582 | osd_req_op_extent_osd_data(osd_req, 0, osd_data); | 1634 | osd_req_op_extent_osd_data(osd_req, 0, osd_data); |
1583 | rbd_osd_req_format(obj_request, write_request); | 1635 | rbd_osd_req_format(obj_request, write_request); |
1584 | 1636 | ||
1585 | /* status and version are initially zero-filled */ | ||
1586 | |||
1587 | rbd_img_obj_request_add(img_request, obj_request); | 1637 | rbd_img_obj_request_add(img_request, obj_request); |
1588 | 1638 | ||
1589 | image_offset += length; | 1639 | image_offset += length; |
@@ -1601,57 +1651,6 @@ out_unwind: | |||
1601 | return -ENOMEM; | 1651 | return -ENOMEM; |
1602 | } | 1652 | } |
1603 | 1653 | ||
1604 | static void rbd_img_obj_callback(struct rbd_obj_request *obj_request) | ||
1605 | { | ||
1606 | struct rbd_img_request *img_request; | ||
1607 | u32 which = obj_request->which; | ||
1608 | bool more = true; | ||
1609 | |||
1610 | img_request = obj_request->img_request; | ||
1611 | |||
1612 | dout("%s: img %p obj %p\n", __func__, img_request, obj_request); | ||
1613 | rbd_assert(img_request != NULL); | ||
1614 | rbd_assert(img_request->rq != NULL); | ||
1615 | rbd_assert(img_request->obj_request_count > 0); | ||
1616 | rbd_assert(which != BAD_WHICH); | ||
1617 | rbd_assert(which < img_request->obj_request_count); | ||
1618 | rbd_assert(which >= img_request->next_completion); | ||
1619 | |||
1620 | spin_lock_irq(&img_request->completion_lock); | ||
1621 | if (which != img_request->next_completion) | ||
1622 | goto out; | ||
1623 | |||
1624 | for_each_obj_request_from(img_request, obj_request) { | ||
1625 | unsigned int xferred; | ||
1626 | int result; | ||
1627 | |||
1628 | rbd_assert(more); | ||
1629 | rbd_assert(which < img_request->obj_request_count); | ||
1630 | |||
1631 | if (!obj_request_done_test(obj_request)) | ||
1632 | break; | ||
1633 | |||
1634 | rbd_assert(obj_request->xferred <= (u64) UINT_MAX); | ||
1635 | xferred = (unsigned int) obj_request->xferred; | ||
1636 | result = (int) obj_request->result; | ||
1637 | if (result) | ||
1638 | rbd_warn(NULL, "obj_request %s result %d xferred %u\n", | ||
1639 | img_request->write_request ? "write" : "read", | ||
1640 | result, xferred); | ||
1641 | |||
1642 | more = blk_end_request(img_request->rq, result, xferred); | ||
1643 | which++; | ||
1644 | } | ||
1645 | |||
1646 | rbd_assert(more ^ (which == img_request->obj_request_count)); | ||
1647 | img_request->next_completion = which; | ||
1648 | out: | ||
1649 | spin_unlock_irq(&img_request->completion_lock); | ||
1650 | |||
1651 | if (!more) | ||
1652 | rbd_img_request_complete(img_request); | ||
1653 | } | ||
1654 | |||
1655 | static int rbd_img_request_submit(struct rbd_img_request *img_request) | 1654 | static int rbd_img_request_submit(struct rbd_img_request *img_request) |
1656 | { | 1655 | { |
1657 | struct rbd_device *rbd_dev = img_request->rbd_dev; | 1656 | struct rbd_device *rbd_dev = img_request->rbd_dev; |
@@ -1663,7 +1662,6 @@ static int rbd_img_request_submit(struct rbd_img_request *img_request) | |||
1663 | for_each_obj_request_safe(img_request, obj_request, next_obj_request) { | 1662 | for_each_obj_request_safe(img_request, obj_request, next_obj_request) { |
1664 | int ret; | 1663 | int ret; |
1665 | 1664 | ||
1666 | obj_request->callback = rbd_img_obj_callback; | ||
1667 | ret = rbd_obj_request_submit(osdc, obj_request); | 1665 | ret = rbd_obj_request_submit(osdc, obj_request); |
1668 | if (ret) | 1666 | if (ret) |
1669 | return ret; | 1667 | return ret; |
@@ -1682,7 +1680,7 @@ static int rbd_obj_notify_ack(struct rbd_device *rbd_dev, | |||
1682 | u64 ver, u64 notify_id) | 1680 | u64 ver, u64 notify_id) |
1683 | { | 1681 | { |
1684 | struct rbd_obj_request *obj_request; | 1682 | struct rbd_obj_request *obj_request; |
1685 | struct ceph_osd_client *osdc; | 1683 | struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc; |
1686 | int ret; | 1684 | int ret; |
1687 | 1685 | ||
1688 | obj_request = rbd_obj_request_create(rbd_dev->header_name, 0, 0, | 1686 | obj_request = rbd_obj_request_create(rbd_dev->header_name, 0, 0, |
@@ -1694,13 +1692,12 @@ static int rbd_obj_notify_ack(struct rbd_device *rbd_dev, | |||
1694 | obj_request->osd_req = rbd_osd_req_create(rbd_dev, false, obj_request); | 1692 | obj_request->osd_req = rbd_osd_req_create(rbd_dev, false, obj_request); |
1695 | if (!obj_request->osd_req) | 1693 | if (!obj_request->osd_req) |
1696 | goto out; | 1694 | goto out; |
1695 | obj_request->callback = rbd_obj_request_put; | ||
1697 | 1696 | ||
1698 | osd_req_op_watch_init(obj_request->osd_req, 0, CEPH_OSD_OP_NOTIFY_ACK, | 1697 | osd_req_op_watch_init(obj_request->osd_req, 0, CEPH_OSD_OP_NOTIFY_ACK, |
1699 | notify_id, ver, 0); | 1698 | notify_id, ver, 0); |
1700 | rbd_osd_req_format(obj_request, false); | 1699 | rbd_osd_req_format(obj_request, false); |
1701 | 1700 | ||
1702 | osdc = &rbd_dev->rbd_client->client->osdc; | ||
1703 | obj_request->callback = rbd_obj_request_put; | ||
1704 | ret = rbd_obj_request_submit(osdc, obj_request); | 1701 | ret = rbd_obj_request_submit(osdc, obj_request); |
1705 | out: | 1702 | out: |
1706 | if (ret) | 1703 | if (ret) |
@@ -1760,16 +1757,17 @@ static int rbd_dev_header_watch_sync(struct rbd_device *rbd_dev, int start) | |||
1760 | if (!obj_request->osd_req) | 1757 | if (!obj_request->osd_req) |
1761 | goto out_cancel; | 1758 | goto out_cancel; |
1762 | 1759 | ||
1763 | osd_req_op_watch_init(obj_request->osd_req, 0, CEPH_OSD_OP_WATCH, | ||
1764 | rbd_dev->watch_event->cookie, | ||
1765 | rbd_dev->header.obj_version, start); | ||
1766 | rbd_osd_req_format(obj_request, true); | ||
1767 | |||
1768 | if (start) | 1760 | if (start) |
1769 | ceph_osdc_set_request_linger(osdc, obj_request->osd_req); | 1761 | ceph_osdc_set_request_linger(osdc, obj_request->osd_req); |
1770 | else | 1762 | else |
1771 | ceph_osdc_unregister_linger_request(osdc, | 1763 | ceph_osdc_unregister_linger_request(osdc, |
1772 | rbd_dev->watch_request->osd_req); | 1764 | rbd_dev->watch_request->osd_req); |
1765 | |||
1766 | osd_req_op_watch_init(obj_request->osd_req, 0, CEPH_OSD_OP_WATCH, | ||
1767 | rbd_dev->watch_event->cookie, | ||
1768 | rbd_dev->header.obj_version, start); | ||
1769 | rbd_osd_req_format(obj_request, true); | ||
1770 | |||
1773 | ret = rbd_obj_request_submit(osdc, obj_request); | 1771 | ret = rbd_obj_request_submit(osdc, obj_request); |
1774 | if (ret) | 1772 | if (ret) |
1775 | goto out_cancel; | 1773 | goto out_cancel; |
@@ -1821,9 +1819,9 @@ static int rbd_obj_method_sync(struct rbd_device *rbd_dev, | |||
1821 | size_t inbound_size, | 1819 | size_t inbound_size, |
1822 | u64 *version) | 1820 | u64 *version) |
1823 | { | 1821 | { |
1822 | struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc; | ||
1824 | struct rbd_obj_request *obj_request; | 1823 | struct rbd_obj_request *obj_request; |
1825 | struct ceph_osd_data *osd_data; | 1824 | struct ceph_osd_data *osd_data; |
1826 | struct ceph_osd_client *osdc; | ||
1827 | struct page **pages; | 1825 | struct page **pages; |
1828 | u32 page_count; | 1826 | u32 page_count; |
1829 | int ret; | 1827 | int ret; |
@@ -1862,7 +1860,6 @@ static int rbd_obj_method_sync(struct rbd_device *rbd_dev, | |||
1862 | osd_req_op_cls_response_data(obj_request->osd_req, 0, osd_data); | 1860 | osd_req_op_cls_response_data(obj_request->osd_req, 0, osd_data); |
1863 | rbd_osd_req_format(obj_request, false); | 1861 | rbd_osd_req_format(obj_request, false); |
1864 | 1862 | ||
1865 | osdc = &rbd_dev->rbd_client->client->osdc; | ||
1866 | ret = rbd_obj_request_submit(osdc, obj_request); | 1863 | ret = rbd_obj_request_submit(osdc, obj_request); |
1867 | if (ret) | 1864 | if (ret) |
1868 | goto out; | 1865 | goto out; |
@@ -2038,9 +2035,9 @@ static int rbd_obj_read_sync(struct rbd_device *rbd_dev, | |||
2038 | char *buf, u64 *version) | 2035 | char *buf, u64 *version) |
2039 | 2036 | ||
2040 | { | 2037 | { |
2038 | struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc; | ||
2041 | struct rbd_obj_request *obj_request; | 2039 | struct rbd_obj_request *obj_request; |
2042 | struct ceph_osd_data *osd_data; | 2040 | struct ceph_osd_data *osd_data; |
2043 | struct ceph_osd_client *osdc; | ||
2044 | struct page **pages = NULL; | 2041 | struct page **pages = NULL; |
2045 | u32 page_count; | 2042 | u32 page_count; |
2046 | size_t size; | 2043 | size_t size; |
@@ -2074,7 +2071,6 @@ static int rbd_obj_read_sync(struct rbd_device *rbd_dev, | |||
2074 | osd_req_op_extent_osd_data(obj_request->osd_req, 0, osd_data); | 2071 | osd_req_op_extent_osd_data(obj_request->osd_req, 0, osd_data); |
2075 | rbd_osd_req_format(obj_request, false); | 2072 | rbd_osd_req_format(obj_request, false); |
2076 | 2073 | ||
2077 | osdc = &rbd_dev->rbd_client->client->osdc; | ||
2078 | ret = rbd_obj_request_submit(osdc, obj_request); | 2074 | ret = rbd_obj_request_submit(osdc, obj_request); |
2079 | if (ret) | 2075 | if (ret) |
2080 | goto out; | 2076 | goto out; |