Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client:
rbd: fix split bio handling
rbd: fix leak of ops struct

+156 -21
+156 -21
drivers/block/rbd.c
··· 92 92 struct list_head node; 93 93 }; 94 94 95 + struct rbd_req_coll; 96 + 95 97 /* 96 98 * a single io request 97 99 */ ··· 102 100 struct bio *bio; /* cloned bio */ 103 101 struct page **pages; /* list of used pages */ 104 102 u64 len; 103 + int coll_index; 104 + struct rbd_req_coll *coll; 105 + }; 106 + 107 + struct rbd_req_status { 108 + int done; 109 + int rc; 110 + u64 bytes; 111 + }; 112 + 113 + /* 114 + * a collection of requests 115 + */ 116 + struct rbd_req_coll { 117 + int total; 118 + int num_done; 119 + struct kref kref; 120 + struct rbd_req_status status[0]; 105 121 }; 106 122 107 123 struct rbd_snap { ··· 436 416 rbd_dev->client = NULL; 437 417 } 438 418 419 + /* 420 + * Destroy requests collection 421 + */ 422 + static void rbd_coll_release(struct kref *kref) 423 + { 424 + struct rbd_req_coll *coll = 425 + container_of(kref, struct rbd_req_coll, kref); 426 + 427 + dout("rbd_coll_release %p\n", coll); 428 + kfree(coll); 429 + } 439 430 440 431 /* 441 432 * Create a new header structure, translate header format from the on-disk ··· 621 590 return len; 622 591 } 623 592 593 + static int rbd_get_num_segments(struct rbd_image_header *header, 594 + u64 ofs, u64 len) 595 + { 596 + u64 start_seg = ofs >> header->obj_order; 597 + u64 end_seg = (ofs + len - 1) >> header->obj_order; 598 + return end_seg - start_seg + 1; 599 + } 600 + 624 601 /* 625 602 * bio helpers 626 603 */ ··· 774 735 kfree(ops); 775 736 } 776 737 738 + static void rbd_coll_end_req_index(struct request *rq, 739 + struct rbd_req_coll *coll, 740 + int index, 741 + int ret, u64 len) 742 + { 743 + struct request_queue *q; 744 + int min, max, i; 745 + 746 + dout("rbd_coll_end_req_index %p index %d ret %d len %lld\n", 747 + coll, index, ret, len); 748 + 749 + if (!rq) 750 + return; 751 + 752 + if (!coll) { 753 + blk_end_request(rq, ret, len); 754 + return; 755 + } 756 + 757 + q = rq->q; 758 + 759 + spin_lock_irq(q->queue_lock); 760 + coll->status[index].done = 1; 761 + coll->status[index].rc = ret; 762 + coll->status[index].bytes = len; 763 + max = min = coll->num_done; 764 + while (max < coll->total && coll->status[max].done) 765 + max++; 766 + 767 + for (i = min; i<max; i++) { 768 + __blk_end_request(rq, coll->status[i].rc, 769 + coll->status[i].bytes); 770 + coll->num_done++; 771 + kref_put(&coll->kref, rbd_coll_release); 772 + } 773 + spin_unlock_irq(q->queue_lock); 774 + } 775 + 776 + static void rbd_coll_end_req(struct rbd_request *req, 777 + int ret, u64 len) 778 + { 779 + rbd_coll_end_req_index(req->rq, req->coll, req->coll_index, ret, len); 780 + } 781 + 777 782 /* 778 783 * Send ceph osd request 779 784 */ ··· 832 749 int flags, 833 750 struct ceph_osd_req_op *ops, 834 751 int num_reply, 752 + struct rbd_req_coll *coll, 753 + int coll_index, 835 754 void (*rbd_cb)(struct ceph_osd_request *req, 836 755 struct ceph_msg *msg), 837 756 struct ceph_osd_request **linger_req, ··· 848 763 struct ceph_osd_request_head *reqhead; 849 764 struct rbd_image_header *header = &dev->header; 850 765 851 - ret = -ENOMEM; 852 766 req_data = kzalloc(sizeof(*req_data), GFP_NOIO); 853 - if (!req_data) 854 - goto done; 767 + if (!req_data) { 768 + if (coll) 769 + rbd_coll_end_req_index(rq, coll, coll_index, 770 + -ENOMEM, len); 771 + return -ENOMEM; 772 + } 855 773 856 - dout("rbd_do_request len=%lld ofs=%lld\n", len, ofs); 774 + if (coll) { 775 + req_data->coll = coll; 776 + req_data->coll_index = coll_index; 777 + } 778 + 779 + dout("rbd_do_request obj=%s ofs=%lld len=%lld\n", obj, len, ofs); 857 780 858 781 down_read(&header->snap_rwsem); 859 782 ··· 921 828 ret = ceph_osdc_wait_request(&dev->client->osdc, req); 922 829 if (ver) 923 830 *ver = le64_to_cpu(req->r_reassert_version.version); 924 - dout("reassert_ver=%lld\n", le64_to_cpu(req->r_reassert_version.version)); 831 + dout("reassert_ver=%lld\n", 832 + le64_to_cpu(req->r_reassert_version.version)); 925 833 ceph_osdc_put_request(req); 926 834 } 927 835 return ret; ··· 931 837 bio_chain_put(req_data->bio); 932 838 ceph_osdc_put_request(req); 933 839 done_pages: 840 + rbd_coll_end_req(req_data, ret, len); 934 841 kfree(req_data); 935 - done: 936 - if (rq) 937 - blk_end_request(rq, ret, len); 938 842 return ret; 939 843 } 940 844 ··· 966 874 bytes = req_data->len; 967 875 } 968 876 969 - blk_end_request(req_data->rq, rc, bytes); 877 + rbd_coll_end_req(req_data, rc, bytes); 970 878 971 879 if (req_data->bio) 972 880 bio_chain_put(req_data->bio); ··· 1026 934 flags, 1027 935 ops, 1028 936 2, 937 + NULL, 0, 1029 938 NULL, 1030 939 linger_req, ver); 1031 940 if (ret < 0) ··· 1052 959 u64 snapid, 1053 960 int opcode, int flags, int num_reply, 1054 961 u64 ofs, u64 len, 1055 - struct bio *bio) 962 + struct bio *bio, 963 + struct rbd_req_coll *coll, 964 + int coll_index) 1056 965 { 1057 966 char *seg_name; 1058 967 u64 seg_ofs; ··· 1090 995 flags, 1091 996 ops, 1092 997 num_reply, 998 + coll, coll_index, 1093 999 rbd_req_cb, 0, NULL); 1000 + 1001 + rbd_destroy_ops(ops); 1094 1002 done: 1095 1003 kfree(seg_name); 1096 1004 return ret; ··· 1106 1008 struct rbd_device *rbd_dev, 1107 1009 struct ceph_snap_context *snapc, 1108 1010 u64 ofs, u64 len, 1109 - struct bio *bio) 1011 + struct bio *bio, 1012 + struct rbd_req_coll *coll, 1013 + int coll_index) 1110 1014 { 1111 1015 return rbd_do_op(rq, rbd_dev, snapc, CEPH_NOSNAP, 1112 1016 CEPH_OSD_OP_WRITE, 1113 1017 CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK, 1114 1018 2, 1115 - ofs, len, bio); 1019 + ofs, len, bio, coll, coll_index); 1116 1020 } 1117 1021 1118 1022 /* ··· 1124 1024 struct rbd_device *rbd_dev, 1125 1025 u64 snapid, 1126 1026 u64 ofs, u64 len, 1127 - struct bio *bio) 1027 + struct bio *bio, 1028 + struct rbd_req_coll *coll, 1029 + int coll_index) 1128 1030 { 1129 1031 return rbd_do_op(rq, rbd_dev, NULL, 1130 1032 (snapid ? snapid : CEPH_NOSNAP), 1131 1033 CEPH_OSD_OP_READ, 1132 1034 CEPH_OSD_FLAG_READ, 1133 1035 2, 1134 - ofs, len, bio); 1036 + ofs, len, bio, coll, coll_index); 1135 1037 } 1136 1038 1137 1039 /* ··· 1165 1063 { 1166 1064 struct ceph_osd_req_op *ops; 1167 1065 struct page **pages = NULL; 1168 - int ret = rbd_create_rw_ops(&ops, 1, CEPH_OSD_OP_NOTIFY_ACK, 0); 1066 + int ret; 1067 + 1068 + ret = rbd_create_rw_ops(&ops, 1, CEPH_OSD_OP_NOTIFY_ACK, 0); 1169 1069 if (ret < 0) 1170 1070 return ret; 1171 1071 ··· 1181 1077 CEPH_OSD_FLAG_READ, 1182 1078 ops, 1183 1079 1, 1080 + NULL, 0, 1184 1081 rbd_simple_req_cb, 0, NULL); 1185 1082 1186 1083 rbd_destroy_ops(ops); ··· 1379 1274 return ret; 1380 1275 } 1381 1276 1277 + static struct rbd_req_coll *rbd_alloc_coll(int num_reqs) 1278 + { 1279 + struct rbd_req_coll *coll = 1280 + kzalloc(sizeof(struct rbd_req_coll) + 1281 + sizeof(struct rbd_req_status) * num_reqs, 1282 + GFP_ATOMIC); 1283 + 1284 + if (!coll) 1285 + return NULL; 1286 + coll->total = num_reqs; 1287 + kref_init(&coll->kref); 1288 + return coll; 1289 + } 1290 + 1382 1291 /* 1383 1292 * block device queue callback 1384 1293 */ ··· 1410 1291 bool do_write; 1411 1292 int size, op_size = 0; 1412 1293 u64 ofs; 1294 + int num_segs, cur_seg = 0; 1295 + struct rbd_req_coll *coll; 1413 1296 1414 1297 /* peek at request from block layer */ 1415 1298 if (!rq) ··· 1442 1321 do_write ? "write" : "read", 1443 1322 size, blk_rq_pos(rq) * 512ULL); 1444 1323 1324 + num_segs = rbd_get_num_segments(&rbd_dev->header, ofs, size); 1325 + coll = rbd_alloc_coll(num_segs); 1326 + if (!coll) { 1327 + spin_lock_irq(q->queue_lock); 1328 + __blk_end_request_all(rq, -ENOMEM); 1329 + goto next; 1330 + } 1331 + 1445 1332 do { 1446 1333 /* a bio clone to be passed down to OSD req */ 1447 1334 dout("rq->bio->bi_vcnt=%d\n", rq->bio->bi_vcnt); ··· 1457 1328 rbd_dev->header.block_name, 1458 1329 ofs, size, 1459 1330 NULL, NULL); 1331 + kref_get(&coll->kref); 1460 1332 bio = bio_chain_clone(&rq_bio, &next_bio, &bp, 1461 1333 op_size, GFP_ATOMIC); 1462 1334 if (!bio) { 1463 - spin_lock_irq(q->queue_lock); 1464 - __blk_end_request_all(rq, -ENOMEM); 1465 - goto next; 1335 + rbd_coll_end_req_index(rq, coll, cur_seg, 1336 + -ENOMEM, op_size); 1337 + goto next_seg; 1466 1338 } 1339 + 1467 1340 1468 1341 /* init OSD command: write or read */ 1469 1342 if (do_write) 1470 1343 rbd_req_write(rq, rbd_dev, 1471 1344 rbd_dev->header.snapc, 1472 1345 ofs, 1473 - op_size, bio); 1346 + op_size, bio, 1347 + coll, cur_seg); 1474 1348 else 1475 1349 rbd_req_read(rq, rbd_dev, 1476 1350 cur_snap_id(rbd_dev), 1477 1351 ofs, 1478 - op_size, bio); 1352 + op_size, bio, 1353 + coll, cur_seg); 1479 1354 1355 + next_seg: 1480 1356 size -= op_size; 1481 1357 ofs += op_size; 1482 1358 1359 + cur_seg++; 1483 1360 rq_bio = next_bio; 1484 1361 } while (size > 0); 1362 + kref_put(&coll->kref, rbd_coll_release); 1485 1363 1486 1364 if (bp) 1487 1365 bio_pair_release(bp); 1488 - 1489 1366 spin_lock_irq(q->queue_lock); 1490 1367 next: 1491 1368 rq = blk_fetch_request(q);