diff options
| -rw-r--r-- | fs/ceph/messenger.c | 219 | ||||
| -rw-r--r-- | fs/ceph/messenger.h | 4 | ||||
| -rw-r--r-- | fs/ceph/osd_client.c | 249 | ||||
| -rw-r--r-- | fs/ceph/osd_client.h | 61 | ||||
| -rw-r--r-- | fs/ceph/pagelist.c | 2 | ||||
| -rw-r--r-- | fs/ceph/pagelist.h | 2 |
6 files changed, 436 insertions, 101 deletions
diff --git a/fs/ceph/messenger.c b/fs/ceph/messenger.c index 2502d76fcec1..17a09b32a591 100644 --- a/fs/ceph/messenger.c +++ b/fs/ceph/messenger.c | |||
| @@ -9,6 +9,8 @@ | |||
| 9 | #include <linux/slab.h> | 9 | #include <linux/slab.h> |
| 10 | #include <linux/socket.h> | 10 | #include <linux/socket.h> |
| 11 | #include <linux/string.h> | 11 | #include <linux/string.h> |
| 12 | #include <linux/bio.h> | ||
| 13 | #include <linux/blkdev.h> | ||
| 12 | #include <net/tcp.h> | 14 | #include <net/tcp.h> |
| 13 | 15 | ||
| 14 | #include "super.h" | 16 | #include "super.h" |
| @@ -529,8 +531,11 @@ static void prepare_write_message(struct ceph_connection *con) | |||
| 529 | if (le32_to_cpu(m->hdr.data_len) > 0) { | 531 | if (le32_to_cpu(m->hdr.data_len) > 0) { |
| 530 | /* initialize page iterator */ | 532 | /* initialize page iterator */ |
| 531 | con->out_msg_pos.page = 0; | 533 | con->out_msg_pos.page = 0; |
| 532 | con->out_msg_pos.page_pos = | 534 | if (m->pages) |
| 533 | le16_to_cpu(m->hdr.data_off) & ~PAGE_MASK; | 535 | con->out_msg_pos.page_pos = |
| 536 | le16_to_cpu(m->hdr.data_off) & ~PAGE_MASK; | ||
| 537 | else | ||
| 538 | con->out_msg_pos.page_pos = 0; | ||
| 534 | con->out_msg_pos.data_pos = 0; | 539 | con->out_msg_pos.data_pos = 0; |
| 535 | con->out_msg_pos.did_page_crc = 0; | 540 | con->out_msg_pos.did_page_crc = 0; |
| 536 | con->out_more = 1; /* data + footer will follow */ | 541 | con->out_more = 1; /* data + footer will follow */ |
| @@ -712,6 +717,31 @@ out: | |||
| 712 | return ret; /* done! */ | 717 | return ret; /* done! */ |
| 713 | } | 718 | } |
| 714 | 719 | ||
| 720 | #ifdef CONFIG_BLOCK | ||
| 721 | static void init_bio_iter(struct bio *bio, struct bio **iter, int *seg) | ||
| 722 | { | ||
| 723 | if (!bio) { | ||
| 724 | *iter = NULL; | ||
| 725 | *seg = 0; | ||
| 726 | return; | ||
| 727 | } | ||
| 728 | *iter = bio; | ||
| 729 | *seg = bio->bi_idx; | ||
| 730 | } | ||
| 731 | |||
| 732 | static void iter_bio_next(struct bio **bio_iter, int *seg) | ||
| 733 | { | ||
| 734 | if (*bio_iter == NULL) | ||
| 735 | return; | ||
| 736 | |||
| 737 | BUG_ON(*seg >= (*bio_iter)->bi_vcnt); | ||
| 738 | |||
| 739 | (*seg)++; | ||
| 740 | if (*seg == (*bio_iter)->bi_vcnt) | ||
| 741 | init_bio_iter((*bio_iter)->bi_next, bio_iter, seg); | ||
| 742 | } | ||
| 743 | #endif | ||
| 744 | |||
| 715 | /* | 745 | /* |
| 716 | * Write as much message data payload as we can. If we finish, queue | 746 | * Write as much message data payload as we can. If we finish, queue |
| 717 | * up the footer. | 747 | * up the footer. |
| @@ -726,21 +756,46 @@ static int write_partial_msg_pages(struct ceph_connection *con) | |||
| 726 | size_t len; | 756 | size_t len; |
| 727 | int crc = con->msgr->nocrc; | 757 | int crc = con->msgr->nocrc; |
| 728 | int ret; | 758 | int ret; |
| 759 | int total_max_write; | ||
| 760 | int in_trail = 0; | ||
| 761 | size_t trail_len = (msg->trail ? msg->trail->length : 0); | ||
| 729 | 762 | ||
| 730 | dout("write_partial_msg_pages %p msg %p page %d/%d offset %d\n", | 763 | dout("write_partial_msg_pages %p msg %p page %d/%d offset %d\n", |
| 731 | con, con->out_msg, con->out_msg_pos.page, con->out_msg->nr_pages, | 764 | con, con->out_msg, con->out_msg_pos.page, con->out_msg->nr_pages, |
| 732 | con->out_msg_pos.page_pos); | 765 | con->out_msg_pos.page_pos); |
| 733 | 766 | ||
| 734 | while (con->out_msg_pos.page < con->out_msg->nr_pages) { | 767 | #ifdef CONFIG_BLOCK |
| 768 | if (msg->bio && !msg->bio_iter) | ||
| 769 | init_bio_iter(msg->bio, &msg->bio_iter, &msg->bio_seg); | ||
| 770 | #endif | ||
| 771 | |||
| 772 | while (data_len > con->out_msg_pos.data_pos) { | ||
| 735 | struct page *page = NULL; | 773 | struct page *page = NULL; |
| 736 | void *kaddr = NULL; | 774 | void *kaddr = NULL; |
| 775 | int max_write = PAGE_SIZE; | ||
| 776 | int page_shift = 0; | ||
| 777 | |||
| 778 | total_max_write = data_len - trail_len - | ||
| 779 | con->out_msg_pos.data_pos; | ||
| 737 | 780 | ||
| 738 | /* | 781 | /* |
| 739 | * if we are calculating the data crc (the default), we need | 782 | * if we are calculating the data crc (the default), we need |
| 740 | * to map the page. if our pages[] has been revoked, use the | 783 | * to map the page. if our pages[] has been revoked, use the |
| 741 | * zero page. | 784 | * zero page. |
| 742 | */ | 785 | */ |
| 743 | if (msg->pages) { | 786 | |
| 787 | /* have we reached the trail part of the data? */ | ||
| 788 | if (con->out_msg_pos.data_pos >= data_len - trail_len) { | ||
| 789 | in_trail = 1; | ||
| 790 | |||
| 791 | total_max_write = data_len - con->out_msg_pos.data_pos; | ||
| 792 | |||
| 793 | page = list_first_entry(&msg->trail->head, | ||
| 794 | struct page, lru); | ||
| 795 | if (crc) | ||
| 796 | kaddr = kmap(page); | ||
| 797 | max_write = PAGE_SIZE; | ||
| 798 | } else if (msg->pages) { | ||
| 744 | page = msg->pages[con->out_msg_pos.page]; | 799 | page = msg->pages[con->out_msg_pos.page]; |
| 745 | if (crc) | 800 | if (crc) |
| 746 | kaddr = kmap(page); | 801 | kaddr = kmap(page); |
| @@ -749,13 +804,25 @@ static int write_partial_msg_pages(struct ceph_connection *con) | |||
| 749 | struct page, lru); | 804 | struct page, lru); |
| 750 | if (crc) | 805 | if (crc) |
| 751 | kaddr = kmap(page); | 806 | kaddr = kmap(page); |
| 807 | #ifdef CONFIG_BLOCK | ||
| 808 | } else if (msg->bio) { | ||
| 809 | struct bio_vec *bv; | ||
| 810 | |||
| 811 | bv = bio_iovec_idx(msg->bio_iter, msg->bio_seg); | ||
| 812 | page = bv->bv_page; | ||
| 813 | page_shift = bv->bv_offset; | ||
| 814 | if (crc) | ||
| 815 | kaddr = kmap(page) + page_shift; | ||
| 816 | max_write = bv->bv_len; | ||
| 817 | #endif | ||
| 752 | } else { | 818 | } else { |
| 753 | page = con->msgr->zero_page; | 819 | page = con->msgr->zero_page; |
| 754 | if (crc) | 820 | if (crc) |
| 755 | kaddr = page_address(con->msgr->zero_page); | 821 | kaddr = page_address(con->msgr->zero_page); |
| 756 | } | 822 | } |
| 757 | len = min((int)(PAGE_SIZE - con->out_msg_pos.page_pos), | 823 | len = min_t(int, max_write - con->out_msg_pos.page_pos, |
| 758 | (int)(data_len - con->out_msg_pos.data_pos)); | 824 | total_max_write); |
| 825 | |||
| 759 | if (crc && !con->out_msg_pos.did_page_crc) { | 826 | if (crc && !con->out_msg_pos.did_page_crc) { |
| 760 | void *base = kaddr + con->out_msg_pos.page_pos; | 827 | void *base = kaddr + con->out_msg_pos.page_pos; |
| 761 | u32 tmpcrc = le32_to_cpu(con->out_msg->footer.data_crc); | 828 | u32 tmpcrc = le32_to_cpu(con->out_msg->footer.data_crc); |
| @@ -765,13 +832,14 @@ static int write_partial_msg_pages(struct ceph_connection *con) | |||
| 765 | cpu_to_le32(crc32c(tmpcrc, base, len)); | 832 | cpu_to_le32(crc32c(tmpcrc, base, len)); |
| 766 | con->out_msg_pos.did_page_crc = 1; | 833 | con->out_msg_pos.did_page_crc = 1; |
| 767 | } | 834 | } |
| 768 | |||
| 769 | ret = kernel_sendpage(con->sock, page, | 835 | ret = kernel_sendpage(con->sock, page, |
| 770 | con->out_msg_pos.page_pos, len, | 836 | con->out_msg_pos.page_pos + page_shift, |
| 837 | len, | ||
| 771 | MSG_DONTWAIT | MSG_NOSIGNAL | | 838 | MSG_DONTWAIT | MSG_NOSIGNAL | |
| 772 | MSG_MORE); | 839 | MSG_MORE); |
| 773 | 840 | ||
| 774 | if (crc && (msg->pages || msg->pagelist)) | 841 | if (crc && |
| 842 | (msg->pages || msg->pagelist || msg->bio || in_trail)) | ||
| 775 | kunmap(page); | 843 | kunmap(page); |
| 776 | 844 | ||
| 777 | if (ret <= 0) | 845 | if (ret <= 0) |
| @@ -783,9 +851,16 @@ static int write_partial_msg_pages(struct ceph_connection *con) | |||
| 783 | con->out_msg_pos.page_pos = 0; | 851 | con->out_msg_pos.page_pos = 0; |
| 784 | con->out_msg_pos.page++; | 852 | con->out_msg_pos.page++; |
| 785 | con->out_msg_pos.did_page_crc = 0; | 853 | con->out_msg_pos.did_page_crc = 0; |
| 786 | if (msg->pagelist) | 854 | if (in_trail) |
| 855 | list_move_tail(&page->lru, | ||
| 856 | &msg->trail->head); | ||
| 857 | else if (msg->pagelist) | ||
| 787 | list_move_tail(&page->lru, | 858 | list_move_tail(&page->lru, |
| 788 | &msg->pagelist->head); | 859 | &msg->pagelist->head); |
| 860 | #ifdef CONFIG_BLOCK | ||
| 861 | else if (msg->bio) | ||
| 862 | iter_bio_next(&msg->bio_iter, &msg->bio_seg); | ||
| 863 | #endif | ||
| 789 | } | 864 | } |
| 790 | } | 865 | } |
| 791 | 866 | ||
| @@ -1305,8 +1380,7 @@ static int read_partial_message_section(struct ceph_connection *con, | |||
| 1305 | struct kvec *section, | 1380 | struct kvec *section, |
| 1306 | unsigned int sec_len, u32 *crc) | 1381 | unsigned int sec_len, u32 *crc) |
| 1307 | { | 1382 | { |
| 1308 | int left; | 1383 | int ret, left; |
| 1309 | int ret; | ||
| 1310 | 1384 | ||
| 1311 | BUG_ON(!section); | 1385 | BUG_ON(!section); |
| 1312 | 1386 | ||
| @@ -1329,13 +1403,83 @@ static int read_partial_message_section(struct ceph_connection *con, | |||
| 1329 | static struct ceph_msg *ceph_alloc_msg(struct ceph_connection *con, | 1403 | static struct ceph_msg *ceph_alloc_msg(struct ceph_connection *con, |
| 1330 | struct ceph_msg_header *hdr, | 1404 | struct ceph_msg_header *hdr, |
| 1331 | int *skip); | 1405 | int *skip); |
| 1406 | |||
| 1407 | |||
| 1408 | static int read_partial_message_pages(struct ceph_connection *con, | ||
| 1409 | struct page **pages, | ||
| 1410 | unsigned data_len, int datacrc) | ||
| 1411 | { | ||
| 1412 | void *p; | ||
| 1413 | int ret; | ||
| 1414 | int left; | ||
| 1415 | |||
| 1416 | left = min((int)(data_len - con->in_msg_pos.data_pos), | ||
| 1417 | (int)(PAGE_SIZE - con->in_msg_pos.page_pos)); | ||
| 1418 | /* (page) data */ | ||
| 1419 | BUG_ON(pages == NULL); | ||
| 1420 | p = kmap(pages[con->in_msg_pos.page]); | ||
| 1421 | ret = ceph_tcp_recvmsg(con->sock, p + con->in_msg_pos.page_pos, | ||
| 1422 | left); | ||
| 1423 | if (ret > 0 && datacrc) | ||
| 1424 | con->in_data_crc = | ||
| 1425 | crc32c(con->in_data_crc, | ||
| 1426 | p + con->in_msg_pos.page_pos, ret); | ||
| 1427 | kunmap(pages[con->in_msg_pos.page]); | ||
| 1428 | if (ret <= 0) | ||
| 1429 | return ret; | ||
| 1430 | con->in_msg_pos.data_pos += ret; | ||
| 1431 | con->in_msg_pos.page_pos += ret; | ||
| 1432 | if (con->in_msg_pos.page_pos == PAGE_SIZE) { | ||
| 1433 | con->in_msg_pos.page_pos = 0; | ||
| 1434 | con->in_msg_pos.page++; | ||
| 1435 | } | ||
| 1436 | |||
| 1437 | return ret; | ||
| 1438 | } | ||
| 1439 | |||
| 1440 | #ifdef CONFIG_BLOCK | ||
| 1441 | static int read_partial_message_bio(struct ceph_connection *con, | ||
| 1442 | struct bio **bio_iter, int *bio_seg, | ||
| 1443 | unsigned data_len, int datacrc) | ||
| 1444 | { | ||
| 1445 | struct bio_vec *bv = bio_iovec_idx(*bio_iter, *bio_seg); | ||
| 1446 | void *p; | ||
| 1447 | int ret, left; | ||
| 1448 | |||
| 1449 | if (IS_ERR(bv)) | ||
| 1450 | return PTR_ERR(bv); | ||
| 1451 | |||
| 1452 | left = min((int)(data_len - con->in_msg_pos.data_pos), | ||
| 1453 | (int)(bv->bv_len - con->in_msg_pos.page_pos)); | ||
| 1454 | |||
| 1455 | p = kmap(bv->bv_page) + bv->bv_offset; | ||
| 1456 | |||
| 1457 | ret = ceph_tcp_recvmsg(con->sock, p + con->in_msg_pos.page_pos, | ||
| 1458 | left); | ||
| 1459 | if (ret > 0 && datacrc) | ||
| 1460 | con->in_data_crc = | ||
| 1461 | crc32c(con->in_data_crc, | ||
| 1462 | p + con->in_msg_pos.page_pos, ret); | ||
| 1463 | kunmap(bv->bv_page); | ||
| 1464 | if (ret <= 0) | ||
| 1465 | return ret; | ||
| 1466 | con->in_msg_pos.data_pos += ret; | ||
| 1467 | con->in_msg_pos.page_pos += ret; | ||
| 1468 | if (con->in_msg_pos.page_pos == bv->bv_len) { | ||
| 1469 | con->in_msg_pos.page_pos = 0; | ||
| 1470 | iter_bio_next(bio_iter, bio_seg); | ||
| 1471 | } | ||
| 1472 | |||
| 1473 | return ret; | ||
| 1474 | } | ||
| 1475 | #endif | ||
| 1476 | |||
| 1332 | /* | 1477 | /* |
| 1333 | * read (part of) a message. | 1478 | * read (part of) a message. |
| 1334 | */ | 1479 | */ |
| 1335 | static int read_partial_message(struct ceph_connection *con) | 1480 | static int read_partial_message(struct ceph_connection *con) |
| 1336 | { | 1481 | { |
| 1337 | struct ceph_msg *m = con->in_msg; | 1482 | struct ceph_msg *m = con->in_msg; |
| 1338 | void *p; | ||
| 1339 | int ret; | 1483 | int ret; |
| 1340 | int to, left; | 1484 | int to, left; |
| 1341 | unsigned front_len, middle_len, data_len, data_off; | 1485 | unsigned front_len, middle_len, data_len, data_off; |
| @@ -1422,7 +1566,10 @@ static int read_partial_message(struct ceph_connection *con) | |||
| 1422 | m->middle->vec.iov_len = 0; | 1566 | m->middle->vec.iov_len = 0; |
| 1423 | 1567 | ||
| 1424 | con->in_msg_pos.page = 0; | 1568 | con->in_msg_pos.page = 0; |
| 1425 | con->in_msg_pos.page_pos = data_off & ~PAGE_MASK; | 1569 | if (m->pages) |
| 1570 | con->in_msg_pos.page_pos = data_off & ~PAGE_MASK; | ||
| 1571 | else | ||
| 1572 | con->in_msg_pos.page_pos = 0; | ||
| 1426 | con->in_msg_pos.data_pos = 0; | 1573 | con->in_msg_pos.data_pos = 0; |
| 1427 | } | 1574 | } |
| 1428 | 1575 | ||
| @@ -1440,27 +1587,29 @@ static int read_partial_message(struct ceph_connection *con) | |||
| 1440 | if (ret <= 0) | 1587 | if (ret <= 0) |
| 1441 | return ret; | 1588 | return ret; |
| 1442 | } | 1589 | } |
| 1590 | #ifdef CONFIG_BLOCK | ||
| 1591 | if (m->bio && !m->bio_iter) | ||
| 1592 | init_bio_iter(m->bio, &m->bio_iter, &m->bio_seg); | ||
| 1593 | #endif | ||
| 1443 | 1594 | ||
| 1444 | /* (page) data */ | 1595 | /* (page) data */ |
| 1445 | while (con->in_msg_pos.data_pos < data_len) { | 1596 | while (con->in_msg_pos.data_pos < data_len) { |
| 1446 | left = min((int)(data_len - con->in_msg_pos.data_pos), | 1597 | if (m->pages) { |
| 1447 | (int)(PAGE_SIZE - con->in_msg_pos.page_pos)); | 1598 | ret = read_partial_message_pages(con, m->pages, |
| 1448 | BUG_ON(m->pages == NULL); | 1599 | data_len, datacrc); |
| 1449 | p = kmap(m->pages[con->in_msg_pos.page]); | 1600 | if (ret <= 0) |
| 1450 | ret = ceph_tcp_recvmsg(con->sock, p + con->in_msg_pos.page_pos, | 1601 | return ret; |
| 1451 | left); | 1602 | #ifdef CONFIG_BLOCK |
| 1452 | if (ret > 0 && datacrc) | 1603 | } else if (m->bio) { |
| 1453 | con->in_data_crc = | 1604 | |
| 1454 | crc32c(con->in_data_crc, | 1605 | ret = read_partial_message_bio(con, |
| 1455 | p + con->in_msg_pos.page_pos, ret); | 1606 | &m->bio_iter, &m->bio_seg, |
| 1456 | kunmap(m->pages[con->in_msg_pos.page]); | 1607 | data_len, datacrc); |
| 1457 | if (ret <= 0) | 1608 | if (ret <= 0) |
| 1458 | return ret; | 1609 | return ret; |
| 1459 | con->in_msg_pos.data_pos += ret; | 1610 | #endif |
| 1460 | con->in_msg_pos.page_pos += ret; | 1611 | } else { |
| 1461 | if (con->in_msg_pos.page_pos == PAGE_SIZE) { | 1612 | BUG_ON(1); |
| 1462 | con->in_msg_pos.page_pos = 0; | ||
| 1463 | con->in_msg_pos.page++; | ||
| 1464 | } | 1613 | } |
| 1465 | } | 1614 | } |
| 1466 | 1615 | ||
| @@ -2136,6 +2285,10 @@ struct ceph_msg *ceph_msg_new(int type, int front_len, gfp_t flags) | |||
| 2136 | m->nr_pages = 0; | 2285 | m->nr_pages = 0; |
| 2137 | m->pages = NULL; | 2286 | m->pages = NULL; |
| 2138 | m->pagelist = NULL; | 2287 | m->pagelist = NULL; |
| 2288 | m->bio = NULL; | ||
| 2289 | m->bio_iter = NULL; | ||
| 2290 | m->bio_seg = 0; | ||
| 2291 | m->trail = NULL; | ||
| 2139 | 2292 | ||
| 2140 | dout("ceph_msg_new %p front %d\n", m, front_len); | 2293 | dout("ceph_msg_new %p front %d\n", m, front_len); |
| 2141 | return m; | 2294 | return m; |
| @@ -2250,6 +2403,8 @@ void ceph_msg_last_put(struct kref *kref) | |||
| 2250 | m->pagelist = NULL; | 2403 | m->pagelist = NULL; |
| 2251 | } | 2404 | } |
| 2252 | 2405 | ||
| 2406 | m->trail = NULL; | ||
| 2407 | |||
| 2253 | if (m->pool) | 2408 | if (m->pool) |
| 2254 | ceph_msgpool_put(m->pool, m); | 2409 | ceph_msgpool_put(m->pool, m); |
| 2255 | else | 2410 | else |
diff --git a/fs/ceph/messenger.h b/fs/ceph/messenger.h index 76fbc957bc13..5a79450604ef 100644 --- a/fs/ceph/messenger.h +++ b/fs/ceph/messenger.h | |||
| @@ -82,6 +82,10 @@ struct ceph_msg { | |||
| 82 | struct ceph_pagelist *pagelist; /* instead of pages */ | 82 | struct ceph_pagelist *pagelist; /* instead of pages */ |
| 83 | struct list_head list_head; | 83 | struct list_head list_head; |
| 84 | struct kref kref; | 84 | struct kref kref; |
| 85 | struct bio *bio; /* instead of pages/pagelist */ | ||
| 86 | struct bio *bio_iter; /* bio iterator */ | ||
| 87 | int bio_seg; /* current bio segment */ | ||
| 88 | struct ceph_pagelist *trail; /* the trailing part of the data */ | ||
| 85 | bool front_is_vmalloc; | 89 | bool front_is_vmalloc; |
| 86 | bool more_to_follow; | 90 | bool more_to_follow; |
| 87 | bool needs_out_seq; | 91 | bool needs_out_seq; |
diff --git a/fs/ceph/osd_client.c b/fs/ceph/osd_client.c index 2647dafd96f5..c5d818e73add 100644 --- a/fs/ceph/osd_client.c +++ b/fs/ceph/osd_client.c | |||
| @@ -6,12 +6,16 @@ | |||
| 6 | #include <linux/pagemap.h> | 6 | #include <linux/pagemap.h> |
| 7 | #include <linux/slab.h> | 7 | #include <linux/slab.h> |
| 8 | #include <linux/uaccess.h> | 8 | #include <linux/uaccess.h> |
| 9 | #ifdef CONFIG_BLOCK | ||
| 10 | #include <linux/bio.h> | ||
| 11 | #endif | ||
| 9 | 12 | ||
| 10 | #include "super.h" | 13 | #include "super.h" |
| 11 | #include "osd_client.h" | 14 | #include "osd_client.h" |
| 12 | #include "messenger.h" | 15 | #include "messenger.h" |
| 13 | #include "decode.h" | 16 | #include "decode.h" |
| 14 | #include "auth.h" | 17 | #include "auth.h" |
| 18 | #include "pagelist.h" | ||
| 15 | 19 | ||
| 16 | #define OSD_OP_FRONT_LEN 4096 | 20 | #define OSD_OP_FRONT_LEN 4096 |
| 17 | #define OSD_OPREPLY_FRONT_LEN 512 | 21 | #define OSD_OPREPLY_FRONT_LEN 512 |
| @@ -22,29 +26,50 @@ static int __kick_requests(struct ceph_osd_client *osdc, | |||
| 22 | 26 | ||
| 23 | static void kick_requests(struct ceph_osd_client *osdc, struct ceph_osd *osd); | 27 | static void kick_requests(struct ceph_osd_client *osdc, struct ceph_osd *osd); |
| 24 | 28 | ||
| 29 | static int op_needs_trail(int op) | ||
| 30 | { | ||
| 31 | switch (op) { | ||
| 32 | case CEPH_OSD_OP_GETXATTR: | ||
| 33 | case CEPH_OSD_OP_SETXATTR: | ||
| 34 | case CEPH_OSD_OP_CMPXATTR: | ||
| 35 | case CEPH_OSD_OP_CALL: | ||
| 36 | return 1; | ||
| 37 | default: | ||
| 38 | return 0; | ||
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 42 | static int op_has_extent(int op) | ||
| 43 | { | ||
| 44 | return (op == CEPH_OSD_OP_READ || | ||
| 45 | op == CEPH_OSD_OP_WRITE); | ||
| 46 | } | ||
| 47 | |||
| 25 | void ceph_calc_raw_layout(struct ceph_osd_client *osdc, | 48 | void ceph_calc_raw_layout(struct ceph_osd_client *osdc, |
| 26 | struct ceph_file_layout *layout, | 49 | struct ceph_file_layout *layout, |
| 27 | u64 snapid, | 50 | u64 snapid, |
| 28 | u64 off, u64 len, u64 *bno, | 51 | u64 off, u64 *plen, u64 *bno, |
| 29 | struct ceph_osd_request *req) | 52 | struct ceph_osd_request *req, |
| 53 | struct ceph_osd_req_op *op) | ||
| 30 | { | 54 | { |
| 31 | struct ceph_osd_request_head *reqhead = req->r_request->front.iov_base; | 55 | struct ceph_osd_request_head *reqhead = req->r_request->front.iov_base; |
| 32 | struct ceph_osd_op *op = (void *)(reqhead + 1); | 56 | u64 orig_len = *plen; |
| 33 | u64 orig_len = len; | ||
| 34 | u64 objoff, objlen; /* extent in object */ | 57 | u64 objoff, objlen; /* extent in object */ |
| 35 | 58 | ||
| 36 | reqhead->snapid = cpu_to_le64(snapid); | 59 | reqhead->snapid = cpu_to_le64(snapid); |
| 37 | 60 | ||
| 38 | /* object extent? */ | 61 | /* object extent? */ |
| 39 | ceph_calc_file_object_mapping(layout, off, &len, bno, | 62 | ceph_calc_file_object_mapping(layout, off, plen, bno, |
| 40 | &objoff, &objlen); | 63 | &objoff, &objlen); |
| 41 | if (len < orig_len) | 64 | if (*plen < orig_len) |
| 42 | dout(" skipping last %llu, final file extent %llu~%llu\n", | 65 | dout(" skipping last %llu, final file extent %llu~%llu\n", |
| 43 | orig_len - len, off, len); | 66 | orig_len - *plen, off, *plen); |
| 44 | 67 | ||
| 45 | op->extent.offset = cpu_to_le64(objoff); | 68 | if (op_has_extent(op->op)) { |
| 46 | op->extent.length = cpu_to_le64(objlen); | 69 | op->extent.offset = objoff; |
| 47 | req->r_num_pages = calc_pages_for(off, len); | 70 | op->extent.length = objlen; |
| 71 | } | ||
| 72 | req->r_num_pages = calc_pages_for(off, *plen); | ||
| 48 | 73 | ||
| 49 | dout("calc_layout bno=%llx %llu~%llu (%d pages)\n", | 74 | dout("calc_layout bno=%llx %llu~%llu (%d pages)\n", |
| 50 | *bno, objoff, objlen, req->r_num_pages); | 75 | *bno, objoff, objlen, req->r_num_pages); |
| @@ -80,11 +105,13 @@ static void calc_layout(struct ceph_osd_client *osdc, | |||
| 80 | struct ceph_vino vino, | 105 | struct ceph_vino vino, |
| 81 | struct ceph_file_layout *layout, | 106 | struct ceph_file_layout *layout, |
| 82 | u64 off, u64 *plen, | 107 | u64 off, u64 *plen, |
| 83 | struct ceph_osd_request *req) | 108 | struct ceph_osd_request *req, |
| 109 | struct ceph_osd_req_op *op) | ||
| 84 | { | 110 | { |
| 85 | u64 bno; | 111 | u64 bno; |
| 86 | 112 | ||
| 87 | ceph_calc_raw_layout(osdc, layout, vino.snap, off, *plen, &bno, req); | 113 | ceph_calc_raw_layout(osdc, layout, vino.snap, off, |
| 114 | plen, &bno, req, op); | ||
| 88 | 115 | ||
| 89 | sprintf(req->r_oid, "%llx.%08llx", vino.ino, bno); | 116 | sprintf(req->r_oid, "%llx.%08llx", vino.ino, bno); |
| 90 | req->r_oid_len = strlen(req->r_oid); | 117 | req->r_oid_len = strlen(req->r_oid); |
| @@ -113,35 +140,64 @@ void ceph_osdc_release_request(struct kref *kref) | |||
| 113 | if (req->r_own_pages) | 140 | if (req->r_own_pages) |
| 114 | ceph_release_page_vector(req->r_pages, | 141 | ceph_release_page_vector(req->r_pages, |
| 115 | req->r_num_pages); | 142 | req->r_num_pages); |
| 143 | #ifdef CONFIG_BLOCK | ||
| 144 | if (req->r_bio) | ||
| 145 | bio_put(req->r_bio); | ||
| 146 | #endif | ||
| 116 | ceph_put_snap_context(req->r_snapc); | 147 | ceph_put_snap_context(req->r_snapc); |
| 148 | if (req->r_trail) { | ||
| 149 | ceph_pagelist_release(req->r_trail); | ||
| 150 | kfree(req->r_trail); | ||
| 151 | } | ||
| 117 | if (req->r_mempool) | 152 | if (req->r_mempool) |
| 118 | mempool_free(req, req->r_osdc->req_mempool); | 153 | mempool_free(req, req->r_osdc->req_mempool); |
| 119 | else | 154 | else |
| 120 | kfree(req); | 155 | kfree(req); |
| 121 | } | 156 | } |
| 122 | 157 | ||
| 158 | static int op_needs_trail(int op) | ||
| 159 | { | ||
| 160 | switch (op) { | ||
| 161 | case CEPH_OSD_OP_GETXATTR: | ||
| 162 | case CEPH_OSD_OP_SETXATTR: | ||
| 163 | case CEPH_OSD_OP_CMPXATTR: | ||
| 164 | return 1; | ||
| 165 | default: | ||
| 166 | return 0; | ||
| 167 | } | ||
| 168 | } | ||
| 169 | |||
| 170 | static int get_num_ops(struct ceph_osd_req_op *ops, int *needs_trail) | ||
| 171 | { | ||
| 172 | int i = 0; | ||
| 173 | |||
| 174 | if (needs_trail) | ||
| 175 | *needs_trail = 0; | ||
| 176 | while (ops[i].op) { | ||
| 177 | if (needs_trail && op_needs_trail(ops[i].op)) | ||
| 178 | *needs_trail = 1; | ||
| 179 | i++; | ||
| 180 | } | ||
| 181 | |||
| 182 | return i; | ||
| 183 | } | ||
| 184 | |||
| 123 | struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc, | 185 | struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc, |
| 124 | int flags, | 186 | int flags, |
| 125 | struct ceph_snap_context *snapc, | 187 | struct ceph_snap_context *snapc, |
| 126 | int do_sync, | 188 | struct ceph_osd_req_op *ops, |
| 127 | bool use_mempool, | 189 | bool use_mempool, |
| 128 | gfp_t gfp_flags, | 190 | gfp_t gfp_flags, |
| 129 | struct page **pages) | 191 | struct page **pages, |
| 192 | struct bio *bio) | ||
| 130 | { | 193 | { |
| 131 | struct ceph_osd_request *req; | 194 | struct ceph_osd_request *req; |
| 132 | struct ceph_msg *msg; | 195 | struct ceph_msg *msg; |
| 133 | int num_op = 1 + do_sync; | 196 | int needs_trail; |
| 134 | size_t msg_size = sizeof(struct ceph_osd_request_head) + | 197 | int num_op = get_num_ops(ops, &needs_trail); |
| 135 | num_op*sizeof(struct ceph_osd_op); | 198 | size_t msg_size = sizeof(struct ceph_osd_request_head); |
| 136 | 199 | ||
| 137 | if (use_mempool) { | 200 | msg_size += num_op*sizeof(struct ceph_osd_op); |
| 138 | req = mempool_alloc(osdc->req_mempool, gfp_flags); | ||
| 139 | memset(req, 0, sizeof(*req)); | ||
| 140 | } else { | ||
| 141 | req = kzalloc(sizeof(*req), gfp_flags); | ||
| 142 | } | ||
| 143 | if (!req) | ||
| 144 | return NULL; | ||
| 145 | 201 | ||
| 146 | if (use_mempool) { | 202 | if (use_mempool) { |
| 147 | req = mempool_alloc(osdc->req_mempool, gfp_flags); | 203 | req = mempool_alloc(osdc->req_mempool, gfp_flags); |
| @@ -154,6 +210,7 @@ struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc, | |||
| 154 | 210 | ||
| 155 | req->r_osdc = osdc; | 211 | req->r_osdc = osdc; |
| 156 | req->r_mempool = use_mempool; | 212 | req->r_mempool = use_mempool; |
| 213 | |||
| 157 | kref_init(&req->r_kref); | 214 | kref_init(&req->r_kref); |
| 158 | init_completion(&req->r_completion); | 215 | init_completion(&req->r_completion); |
| 159 | init_completion(&req->r_safe_completion); | 216 | init_completion(&req->r_safe_completion); |
| @@ -174,6 +231,15 @@ struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc, | |||
| 174 | } | 231 | } |
| 175 | req->r_reply = msg; | 232 | req->r_reply = msg; |
| 176 | 233 | ||
| 234 | /* allocate space for the trailing data */ | ||
| 235 | if (needs_trail) { | ||
| 236 | req->r_trail = kmalloc(sizeof(struct ceph_pagelist), gfp_flags); | ||
| 237 | if (!req->r_trail) { | ||
| 238 | ceph_osdc_put_request(req); | ||
| 239 | return NULL; | ||
| 240 | } | ||
| 241 | ceph_pagelist_init(req->r_trail); | ||
| 242 | } | ||
| 177 | /* create request message; allow space for oid */ | 243 | /* create request message; allow space for oid */ |
| 178 | msg_size += 40; | 244 | msg_size += 40; |
| 179 | if (snapc) | 245 | if (snapc) |
| @@ -186,38 +252,87 @@ struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc, | |||
| 186 | ceph_osdc_put_request(req); | 252 | ceph_osdc_put_request(req); |
| 187 | return NULL; | 253 | return NULL; |
| 188 | } | 254 | } |
| 255 | |||
| 189 | msg->hdr.type = cpu_to_le16(CEPH_MSG_OSD_OP); | 256 | msg->hdr.type = cpu_to_le16(CEPH_MSG_OSD_OP); |
| 190 | memset(msg->front.iov_base, 0, msg->front.iov_len); | 257 | memset(msg->front.iov_base, 0, msg->front.iov_len); |
| 191 | 258 | ||
| 192 | req->r_request = msg; | 259 | req->r_request = msg; |
| 193 | req->r_pages = pages; | 260 | req->r_pages = pages; |
| 261 | #ifdef CONFIG_BLOCK | ||
| 262 | if (bio) { | ||
| 263 | req->r_bio = bio; | ||
| 264 | bio_get(req->r_bio); | ||
| 265 | } | ||
| 266 | #endif | ||
| 194 | 267 | ||
| 195 | return req; | 268 | return req; |
| 196 | } | 269 | } |
| 197 | 270 | ||
| 271 | static void osd_req_encode_op(struct ceph_osd_request *req, | ||
| 272 | struct ceph_osd_op *dst, | ||
| 273 | struct ceph_osd_req_op *src) | ||
| 274 | { | ||
| 275 | dst->op = cpu_to_le16(src->op); | ||
| 276 | |||
| 277 | switch (dst->op) { | ||
| 278 | case CEPH_OSD_OP_READ: | ||
| 279 | case CEPH_OSD_OP_WRITE: | ||
| 280 | dst->extent.offset = | ||
| 281 | cpu_to_le64(src->extent.offset); | ||
| 282 | dst->extent.length = | ||
| 283 | cpu_to_le64(src->extent.length); | ||
| 284 | dst->extent.truncate_size = | ||
| 285 | cpu_to_le64(src->extent.truncate_size); | ||
| 286 | dst->extent.truncate_seq = | ||
| 287 | cpu_to_le32(src->extent.truncate_seq); | ||
| 288 | break; | ||
| 289 | |||
| 290 | case CEPH_OSD_OP_GETXATTR: | ||
| 291 | case CEPH_OSD_OP_SETXATTR: | ||
| 292 | case CEPH_OSD_OP_CMPXATTR: | ||
| 293 | BUG_ON(!req->r_trail); | ||
| 294 | |||
| 295 | dst->xattr.name_len = cpu_to_le32(src->xattr.name_len); | ||
| 296 | dst->xattr.value_len = cpu_to_le32(src->xattr.value_len); | ||
| 297 | dst->xattr.cmp_op = src->xattr.cmp_op; | ||
| 298 | dst->xattr.cmp_mode = src->xattr.cmp_mode; | ||
| 299 | ceph_pagelist_append(req->r_trail, src->xattr.name, | ||
| 300 | src->xattr.name_len); | ||
| 301 | ceph_pagelist_append(req->r_trail, src->xattr.val, | ||
| 302 | src->xattr.value_len); | ||
| 303 | break; | ||
| 304 | case CEPH_OSD_OP_STARTSYNC: | ||
| 305 | break; | ||
| 306 | default: | ||
| 307 | pr_err("unrecognized osd opcode %d\n", dst->op); | ||
| 308 | WARN_ON(1); | ||
| 309 | break; | ||
| 310 | } | ||
| 311 | dst->payload_len = cpu_to_le32(src->payload_len); | ||
| 312 | } | ||
| 313 | |||
| 198 | /* | 314 | /* |
| 199 | * build new request AND message | 315 | * build new request AND message |
| 200 | * | 316 | * |
| 201 | */ | 317 | */ |
| 202 | void ceph_osdc_build_request(struct ceph_osd_request *req, | 318 | void ceph_osdc_build_request(struct ceph_osd_request *req, |
| 203 | u64 off, u64 *plen, | 319 | u64 off, u64 *plen, |
| 204 | int opcode, | 320 | struct ceph_osd_req_op *src_ops, |
| 205 | struct ceph_snap_context *snapc, | 321 | struct ceph_snap_context *snapc, |
| 206 | int do_sync, | 322 | struct timespec *mtime, |
| 207 | u32 truncate_seq, | 323 | const char *oid, |
| 208 | u64 truncate_size, | 324 | int oid_len) |
| 209 | struct timespec *mtime, | ||
| 210 | const char *oid, | ||
| 211 | int oid_len) | ||
| 212 | { | 325 | { |
| 213 | struct ceph_msg *msg = req->r_request; | 326 | struct ceph_msg *msg = req->r_request; |
| 214 | struct ceph_osd_request_head *head; | 327 | struct ceph_osd_request_head *head; |
| 328 | struct ceph_osd_req_op *src_op; | ||
| 215 | struct ceph_osd_op *op; | 329 | struct ceph_osd_op *op; |
| 216 | void *p; | 330 | void *p; |
| 217 | int num_op = 1 + do_sync; | 331 | int num_op = get_num_ops(src_ops, NULL); |
| 218 | size_t msg_size = sizeof(*head) + num_op*sizeof(*op); | 332 | size_t msg_size = sizeof(*head) + num_op*sizeof(*op); |
| 219 | int i; | ||
| 220 | int flags = req->r_flags; | 333 | int flags = req->r_flags; |
| 334 | u64 data_len = 0; | ||
| 335 | int i; | ||
| 221 | 336 | ||
| 222 | head = msg->front.iov_base; | 337 | head = msg->front.iov_base; |
| 223 | op = (void *)(head + 1); | 338 | op = (void *)(head + 1); |
| @@ -230,25 +345,23 @@ void ceph_osdc_build_request(struct ceph_osd_request *req, | |||
| 230 | if (flags & CEPH_OSD_FLAG_WRITE) | 345 | if (flags & CEPH_OSD_FLAG_WRITE) |
| 231 | ceph_encode_timespec(&head->mtime, mtime); | 346 | ceph_encode_timespec(&head->mtime, mtime); |
| 232 | head->num_ops = cpu_to_le16(num_op); | 347 | head->num_ops = cpu_to_le16(num_op); |
| 233 | op->op = cpu_to_le16(opcode); | ||
| 234 | 348 | ||
| 235 | if (flags & CEPH_OSD_FLAG_WRITE) { | ||
| 236 | req->r_request->hdr.data_off = cpu_to_le16(off); | ||
| 237 | req->r_request->hdr.data_len = cpu_to_le32(*plen); | ||
| 238 | op->payload_len = cpu_to_le32(*plen); | ||
| 239 | } | ||
| 240 | op->extent.truncate_size = cpu_to_le64(truncate_size); | ||
| 241 | op->extent.truncate_seq = cpu_to_le32(truncate_seq); | ||
| 242 | 349 | ||
| 243 | /* fill in oid */ | 350 | /* fill in oid */ |
| 244 | head->object_len = cpu_to_le32(oid_len); | 351 | head->object_len = cpu_to_le32(oid_len); |
| 245 | memcpy(p, oid, oid_len); | 352 | memcpy(p, oid, oid_len); |
| 246 | p += oid_len; | 353 | p += oid_len; |
| 247 | 354 | ||
| 248 | if (do_sync) { | 355 | src_op = src_ops; |
| 356 | while (src_op->op) { | ||
| 357 | osd_req_encode_op(req, op, src_op); | ||
| 358 | src_op++; | ||
| 249 | op++; | 359 | op++; |
| 250 | op->op = cpu_to_le16(CEPH_OSD_OP_STARTSYNC); | ||
| 251 | } | 360 | } |
| 361 | |||
| 362 | if (req->r_trail) | ||
| 363 | data_len += req->r_trail->length; | ||
| 364 | |||
| 252 | if (snapc) { | 365 | if (snapc) { |
| 253 | head->snap_seq = cpu_to_le64(snapc->seq); | 366 | head->snap_seq = cpu_to_le64(snapc->seq); |
| 254 | head->num_snaps = cpu_to_le32(snapc->num_snaps); | 367 | head->num_snaps = cpu_to_le32(snapc->num_snaps); |
| @@ -258,6 +371,14 @@ void ceph_osdc_build_request(struct ceph_osd_request *req, | |||
| 258 | } | 371 | } |
| 259 | } | 372 | } |
| 260 | 373 | ||
| 374 | if (flags & CEPH_OSD_FLAG_WRITE) { | ||
| 375 | req->r_request->hdr.data_off = cpu_to_le16(off); | ||
| 376 | req->r_request->hdr.data_len = cpu_to_le32(*plen + data_len); | ||
| 377 | } else if (data_len) { | ||
| 378 | req->r_request->hdr.data_off = 0; | ||
| 379 | req->r_request->hdr.data_len = cpu_to_le32(data_len); | ||
| 380 | } | ||
| 381 | |||
| 261 | BUG_ON(p > msg->front.iov_base + msg->front.iov_len); | 382 | BUG_ON(p > msg->front.iov_base + msg->front.iov_len); |
| 262 | msg_size = p - msg->front.iov_base; | 383 | msg_size = p - msg->front.iov_base; |
| 263 | msg->front.iov_len = msg_size; | 384 | msg->front.iov_len = msg_size; |
| @@ -288,21 +409,34 @@ struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc, | |||
| 288 | struct timespec *mtime, | 409 | struct timespec *mtime, |
| 289 | bool use_mempool, int num_reply) | 410 | bool use_mempool, int num_reply) |
| 290 | { | 411 | { |
| 291 | struct ceph_osd_request *req = | 412 | struct ceph_osd_req_op ops[3]; |
| 292 | ceph_osdc_alloc_request(osdc, flags, | 413 | struct ceph_osd_request *req; |
| 293 | snapc, do_sync, | 414 | |
| 415 | ops[0].op = opcode; | ||
| 416 | ops[0].extent.truncate_seq = truncate_seq; | ||
| 417 | ops[0].extent.truncate_size = truncate_size; | ||
| 418 | ops[0].payload_len = 0; | ||
| 419 | |||
| 420 | if (do_sync) { | ||
| 421 | ops[1].op = CEPH_OSD_OP_STARTSYNC; | ||
| 422 | ops[1].payload_len = 0; | ||
| 423 | ops[2].op = 0; | ||
| 424 | } else | ||
| 425 | ops[1].op = 0; | ||
| 426 | |||
| 427 | req = ceph_osdc_alloc_request(osdc, flags, | ||
| 428 | snapc, ops, | ||
| 294 | use_mempool, | 429 | use_mempool, |
| 295 | GFP_NOFS, NULL); | 430 | GFP_NOFS, NULL, NULL); |
| 296 | if (IS_ERR(req)) | 431 | if (IS_ERR(req)) |
| 297 | return req; | 432 | return req; |
| 298 | 433 | ||
| 299 | /* calculate max write size */ | 434 | /* calculate max write size */ |
| 300 | calc_layout(osdc, vino, layout, off, plen, req); | 435 | calc_layout(osdc, vino, layout, off, plen, req, ops); |
| 301 | req->r_file_layout = *layout; /* keep a copy */ | 436 | req->r_file_layout = *layout; /* keep a copy */ |
| 302 | 437 | ||
| 303 | ceph_osdc_build_request(req, off, plen, opcode, | 438 | ceph_osdc_build_request(req, off, plen, ops, |
| 304 | snapc, do_sync, | 439 | snapc, |
| 305 | truncate_seq, truncate_size, | ||
| 306 | mtime, | 440 | mtime, |
| 307 | req->r_oid, req->r_oid_len); | 441 | req->r_oid, req->r_oid_len); |
| 308 | 442 | ||
| @@ -1177,6 +1311,10 @@ int ceph_osdc_start_request(struct ceph_osd_client *osdc, | |||
| 1177 | 1311 | ||
| 1178 | req->r_request->pages = req->r_pages; | 1312 | req->r_request->pages = req->r_pages; |
| 1179 | req->r_request->nr_pages = req->r_num_pages; | 1313 | req->r_request->nr_pages = req->r_num_pages; |
| 1314 | #ifdef CONFIG_BLOCK | ||
| 1315 | req->r_request->bio = req->r_bio; | ||
| 1316 | #endif | ||
| 1317 | req->r_request->trail = req->r_trail; | ||
| 1180 | 1318 | ||
| 1181 | register_request(osdc, req); | 1319 | register_request(osdc, req); |
| 1182 | 1320 | ||
| @@ -1493,6 +1631,9 @@ static struct ceph_msg *get_reply(struct ceph_connection *con, | |||
| 1493 | } | 1631 | } |
| 1494 | m->pages = req->r_pages; | 1632 | m->pages = req->r_pages; |
| 1495 | m->nr_pages = req->r_num_pages; | 1633 | m->nr_pages = req->r_num_pages; |
| 1634 | #ifdef CONFIG_BLOCK | ||
| 1635 | m->bio = req->r_bio; | ||
| 1636 | #endif | ||
| 1496 | } | 1637 | } |
| 1497 | *skip = 0; | 1638 | *skip = 0; |
| 1498 | req->r_con_filling_msg = ceph_con_get(con); | 1639 | req->r_con_filling_msg = ceph_con_get(con); |
diff --git a/fs/ceph/osd_client.h b/fs/ceph/osd_client.h index b687c2ea72e6..d583d1bf6cd9 100644 --- a/fs/ceph/osd_client.h +++ b/fs/ceph/osd_client.h | |||
| @@ -15,6 +15,7 @@ struct ceph_snap_context; | |||
| 15 | struct ceph_osd_request; | 15 | struct ceph_osd_request; |
| 16 | struct ceph_osd_client; | 16 | struct ceph_osd_client; |
| 17 | struct ceph_authorizer; | 17 | struct ceph_authorizer; |
| 18 | struct ceph_pagelist; | ||
| 18 | 19 | ||
| 19 | /* | 20 | /* |
| 20 | * completion callback for async writepages | 21 | * completion callback for async writepages |
| @@ -80,6 +81,11 @@ struct ceph_osd_request { | |||
| 80 | struct page **r_pages; /* pages for data payload */ | 81 | struct page **r_pages; /* pages for data payload */ |
| 81 | int r_pages_from_pool; | 82 | int r_pages_from_pool; |
| 82 | int r_own_pages; /* if true, i own page list */ | 83 | int r_own_pages; /* if true, i own page list */ |
| 84 | #ifdef CONFIG_BLOCK | ||
| 85 | struct bio *r_bio; /* instead of pages */ | ||
| 86 | #endif | ||
| 87 | |||
| 88 | struct ceph_pagelist *r_trail; /* trailing part of the data */ | ||
| 83 | }; | 89 | }; |
| 84 | 90 | ||
| 85 | struct ceph_osd_client { | 91 | struct ceph_osd_client { |
| @@ -110,6 +116,36 @@ struct ceph_osd_client { | |||
| 110 | struct ceph_msgpool msgpool_op_reply; | 116 | struct ceph_msgpool msgpool_op_reply; |
| 111 | }; | 117 | }; |
| 112 | 118 | ||
| 119 | struct ceph_osd_req_op { | ||
| 120 | u16 op; /* CEPH_OSD_OP_* */ | ||
| 121 | u32 flags; /* CEPH_OSD_FLAG_* */ | ||
| 122 | union { | ||
| 123 | struct { | ||
| 124 | u64 offset, length; | ||
| 125 | u64 truncate_size; | ||
| 126 | u32 truncate_seq; | ||
| 127 | } extent; | ||
| 128 | struct { | ||
| 129 | const char *name; | ||
| 130 | u32 name_len; | ||
| 131 | const char *val; | ||
| 132 | u32 value_len; | ||
| 133 | __u8 cmp_op; /* CEPH_OSD_CMPXATTR_OP_* */ | ||
| 134 | __u8 cmp_mode; /* CEPH_OSD_CMPXATTR_MODE_* */ | ||
| 135 | } xattr; | ||
| 136 | struct { | ||
| 137 | __u8 class_len; | ||
| 138 | __u8 method_len; | ||
| 139 | __u8 argc; | ||
| 140 | u32 indata_len; | ||
| 141 | } cls; | ||
| 142 | struct { | ||
| 143 | u64 cookie, count; | ||
| 144 | } pgls; | ||
| 145 | }; | ||
| 146 | u32 payload_len; | ||
| 147 | }; | ||
| 148 | |||
| 113 | extern int ceph_osdc_init(struct ceph_osd_client *osdc, | 149 | extern int ceph_osdc_init(struct ceph_osd_client *osdc, |
| 114 | struct ceph_client *client); | 150 | struct ceph_client *client); |
| 115 | extern void ceph_osdc_stop(struct ceph_osd_client *osdc); | 151 | extern void ceph_osdc_stop(struct ceph_osd_client *osdc); |
| @@ -122,27 +158,26 @@ extern void ceph_osdc_handle_map(struct ceph_osd_client *osdc, | |||
| 122 | extern void ceph_calc_raw_layout(struct ceph_osd_client *osdc, | 158 | extern void ceph_calc_raw_layout(struct ceph_osd_client *osdc, |
| 123 | struct ceph_file_layout *layout, | 159 | struct ceph_file_layout *layout, |
| 124 | u64 snapid, | 160 | u64 snapid, |
| 125 | u64 off, u64 len, u64 *bno, | 161 | u64 off, u64 *plen, u64 *bno, |
| 126 | struct ceph_osd_request *req); | 162 | struct ceph_osd_request *req, |
| 163 | struct ceph_osd_req_op *op); | ||
| 127 | 164 | ||
| 128 | extern struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc, | 165 | extern struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc, |
| 129 | int flags, | 166 | int flags, |
| 130 | struct ceph_snap_context *snapc, | 167 | struct ceph_snap_context *snapc, |
| 131 | int do_sync, | 168 | struct ceph_osd_req_op *ops, |
| 132 | bool use_mempool, | 169 | bool use_mempool, |
| 133 | gfp_t gfp_flags, | 170 | gfp_t gfp_flags, |
| 134 | struct page **pages); | 171 | struct page **pages, |
| 172 | struct bio *bio); | ||
| 135 | 173 | ||
| 136 | extern void ceph_osdc_build_request(struct ceph_osd_request *req, | 174 | extern void ceph_osdc_build_request(struct ceph_osd_request *req, |
| 137 | u64 off, u64 *plen, | 175 | u64 off, u64 *plen, |
| 138 | int opcode, | 176 | struct ceph_osd_req_op *src_ops, |
| 139 | struct ceph_snap_context *snapc, | 177 | struct ceph_snap_context *snapc, |
| 140 | int do_sync, | 178 | struct timespec *mtime, |
| 141 | u32 truncate_seq, | 179 | const char *oid, |
| 142 | u64 truncate_size, | 180 | int oid_len); |
| 143 | struct timespec *mtime, | ||
| 144 | const char *oid, | ||
| 145 | int oid_len); | ||
| 146 | 181 | ||
| 147 | extern struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *, | 182 | extern struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *, |
| 148 | struct ceph_file_layout *layout, | 183 | struct ceph_file_layout *layout, |
diff --git a/fs/ceph/pagelist.c b/fs/ceph/pagelist.c index 46a368b6dce5..326e1c04176f 100644 --- a/fs/ceph/pagelist.c +++ b/fs/ceph/pagelist.c | |||
| @@ -39,7 +39,7 @@ static int ceph_pagelist_addpage(struct ceph_pagelist *pl) | |||
| 39 | return 0; | 39 | return 0; |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | int ceph_pagelist_append(struct ceph_pagelist *pl, void *buf, size_t len) | 42 | int ceph_pagelist_append(struct ceph_pagelist *pl, const void *buf, size_t len) |
| 43 | { | 43 | { |
| 44 | while (pl->room < len) { | 44 | while (pl->room < len) { |
| 45 | size_t bit = pl->room; | 45 | size_t bit = pl->room; |
diff --git a/fs/ceph/pagelist.h b/fs/ceph/pagelist.h index e8a4187e1087..cc9327aa1c98 100644 --- a/fs/ceph/pagelist.h +++ b/fs/ceph/pagelist.h | |||
| @@ -19,7 +19,7 @@ static inline void ceph_pagelist_init(struct ceph_pagelist *pl) | |||
| 19 | } | 19 | } |
| 20 | extern int ceph_pagelist_release(struct ceph_pagelist *pl); | 20 | extern int ceph_pagelist_release(struct ceph_pagelist *pl); |
| 21 | 21 | ||
| 22 | extern int ceph_pagelist_append(struct ceph_pagelist *pl, void *d, size_t l); | 22 | extern int ceph_pagelist_append(struct ceph_pagelist *pl, const void *d, size_t l); |
| 23 | 23 | ||
| 24 | static inline int ceph_pagelist_encode_64(struct ceph_pagelist *pl, u64 v) | 24 | static inline int ceph_pagelist_encode_64(struct ceph_pagelist *pl, u64 v) |
| 25 | { | 25 | { |
