diff options
author | Sage Weil <sage@inktank.com> | 2012-09-24 23:59:48 -0400 |
---|---|---|
committer | Alex Elder <elder@inktank.com> | 2012-10-01 18:20:00 -0400 |
commit | d63b77f4c552cc3a20506871046ab0fcbc332609 (patch) | |
tree | a428fe42c092c0f6126a99fbc788ae96e8922a97 /net | |
parent | b905a7f8b7a61c192927d0324f2ea6c998f451ba (diff) |
libceph: check for invalid mapping
If we encounter an invalid (e.g., zeroed) mapping, return an error
and avoid a divide by zero.
Signed-off-by: Sage Weil <sage@inktank.com>
Reviewed-by: Alex Elder <elder@inktank.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/ceph/osd_client.c | 32 | ||||
-rw-r--r-- | net/ceph/osdmap.c | 18 |
2 files changed, 36 insertions, 14 deletions
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 42119c05e82c..f7b56e23988c 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c | |||
@@ -52,7 +52,7 @@ static int op_has_extent(int op) | |||
52 | op == CEPH_OSD_OP_WRITE); | 52 | op == CEPH_OSD_OP_WRITE); |
53 | } | 53 | } |
54 | 54 | ||
55 | void ceph_calc_raw_layout(struct ceph_osd_client *osdc, | 55 | int ceph_calc_raw_layout(struct ceph_osd_client *osdc, |
56 | struct ceph_file_layout *layout, | 56 | struct ceph_file_layout *layout, |
57 | u64 snapid, | 57 | u64 snapid, |
58 | u64 off, u64 *plen, u64 *bno, | 58 | u64 off, u64 *plen, u64 *bno, |
@@ -62,12 +62,15 @@ void ceph_calc_raw_layout(struct ceph_osd_client *osdc, | |||
62 | struct ceph_osd_request_head *reqhead = req->r_request->front.iov_base; | 62 | struct ceph_osd_request_head *reqhead = req->r_request->front.iov_base; |
63 | u64 orig_len = *plen; | 63 | u64 orig_len = *plen; |
64 | u64 objoff, objlen; /* extent in object */ | 64 | u64 objoff, objlen; /* extent in object */ |
65 | int r; | ||
65 | 66 | ||
66 | reqhead->snapid = cpu_to_le64(snapid); | 67 | reqhead->snapid = cpu_to_le64(snapid); |
67 | 68 | ||
68 | /* object extent? */ | 69 | /* object extent? */ |
69 | ceph_calc_file_object_mapping(layout, off, plen, bno, | 70 | r = ceph_calc_file_object_mapping(layout, off, plen, bno, |
70 | &objoff, &objlen); | 71 | &objoff, &objlen); |
72 | if (r < 0) | ||
73 | return r; | ||
71 | if (*plen < orig_len) | 74 | if (*plen < orig_len) |
72 | dout(" skipping last %llu, final file extent %llu~%llu\n", | 75 | dout(" skipping last %llu, final file extent %llu~%llu\n", |
73 | orig_len - *plen, off, *plen); | 76 | orig_len - *plen, off, *plen); |
@@ -83,7 +86,7 @@ void ceph_calc_raw_layout(struct ceph_osd_client *osdc, | |||
83 | 86 | ||
84 | dout("calc_layout bno=%llx %llu~%llu (%d pages)\n", | 87 | dout("calc_layout bno=%llx %llu~%llu (%d pages)\n", |
85 | *bno, objoff, objlen, req->r_num_pages); | 88 | *bno, objoff, objlen, req->r_num_pages); |
86 | 89 | return 0; | |
87 | } | 90 | } |
88 | EXPORT_SYMBOL(ceph_calc_raw_layout); | 91 | EXPORT_SYMBOL(ceph_calc_raw_layout); |
89 | 92 | ||
@@ -112,20 +115,25 @@ EXPORT_SYMBOL(ceph_calc_raw_layout); | |||
112 | * | 115 | * |
113 | * fill osd op in request message. | 116 | * fill osd op in request message. |
114 | */ | 117 | */ |
115 | static void calc_layout(struct ceph_osd_client *osdc, | 118 | static int calc_layout(struct ceph_osd_client *osdc, |
116 | struct ceph_vino vino, | 119 | struct ceph_vino vino, |
117 | struct ceph_file_layout *layout, | 120 | struct ceph_file_layout *layout, |
118 | u64 off, u64 *plen, | 121 | u64 off, u64 *plen, |
119 | struct ceph_osd_request *req, | 122 | struct ceph_osd_request *req, |
120 | struct ceph_osd_req_op *op) | 123 | struct ceph_osd_req_op *op) |
121 | { | 124 | { |
122 | u64 bno; | 125 | u64 bno; |
126 | int r; | ||
123 | 127 | ||
124 | ceph_calc_raw_layout(osdc, layout, vino.snap, off, | 128 | r = ceph_calc_raw_layout(osdc, layout, vino.snap, off, |
125 | plen, &bno, req, op); | 129 | plen, &bno, req, op); |
130 | if (r < 0) | ||
131 | return r; | ||
126 | 132 | ||
127 | snprintf(req->r_oid, sizeof(req->r_oid), "%llx.%08llx", vino.ino, bno); | 133 | snprintf(req->r_oid, sizeof(req->r_oid), "%llx.%08llx", vino.ino, bno); |
128 | req->r_oid_len = strlen(req->r_oid); | 134 | req->r_oid_len = strlen(req->r_oid); |
135 | |||
136 | return r; | ||
129 | } | 137 | } |
130 | 138 | ||
131 | /* | 139 | /* |
diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c index 3124b71a8883..5433fb0eb3c6 100644 --- a/net/ceph/osdmap.c +++ b/net/ceph/osdmap.c | |||
@@ -984,7 +984,7 @@ bad: | |||
984 | * for now, we write only a single su, until we can | 984 | * for now, we write only a single su, until we can |
985 | * pass a stride back to the caller. | 985 | * pass a stride back to the caller. |
986 | */ | 986 | */ |
987 | void ceph_calc_file_object_mapping(struct ceph_file_layout *layout, | 987 | int ceph_calc_file_object_mapping(struct ceph_file_layout *layout, |
988 | u64 off, u64 *plen, | 988 | u64 off, u64 *plen, |
989 | u64 *ono, | 989 | u64 *ono, |
990 | u64 *oxoff, u64 *oxlen) | 990 | u64 *oxoff, u64 *oxlen) |
@@ -998,11 +998,17 @@ void ceph_calc_file_object_mapping(struct ceph_file_layout *layout, | |||
998 | 998 | ||
999 | dout("mapping %llu~%llu osize %u fl_su %u\n", off, *plen, | 999 | dout("mapping %llu~%llu osize %u fl_su %u\n", off, *plen, |
1000 | osize, su); | 1000 | osize, su); |
1001 | if (su == 0 || sc == 0) | ||
1002 | goto invalid; | ||
1001 | su_per_object = osize / su; | 1003 | su_per_object = osize / su; |
1004 | if (su_per_object == 0) | ||
1005 | goto invalid; | ||
1002 | dout("osize %u / su %u = su_per_object %u\n", osize, su, | 1006 | dout("osize %u / su %u = su_per_object %u\n", osize, su, |
1003 | su_per_object); | 1007 | su_per_object); |
1004 | 1008 | ||
1005 | BUG_ON((su & ~PAGE_MASK) != 0); | 1009 | if ((su & ~PAGE_MASK) != 0) |
1010 | goto invalid; | ||
1011 | |||
1006 | /* bl = *off / su; */ | 1012 | /* bl = *off / su; */ |
1007 | t = off; | 1013 | t = off; |
1008 | do_div(t, su); | 1014 | do_div(t, su); |
@@ -1030,6 +1036,14 @@ void ceph_calc_file_object_mapping(struct ceph_file_layout *layout, | |||
1030 | *plen = *oxlen; | 1036 | *plen = *oxlen; |
1031 | 1037 | ||
1032 | dout(" obj extent %llu~%llu\n", *oxoff, *oxlen); | 1038 | dout(" obj extent %llu~%llu\n", *oxoff, *oxlen); |
1039 | return 0; | ||
1040 | |||
1041 | invalid: | ||
1042 | dout(" invalid layout\n"); | ||
1043 | *ono = 0; | ||
1044 | *oxoff = 0; | ||
1045 | *oxlen = 0; | ||
1046 | return -EINVAL; | ||
1033 | } | 1047 | } |
1034 | EXPORT_SYMBOL(ceph_calc_file_object_mapping); | 1048 | EXPORT_SYMBOL(ceph_calc_file_object_mapping); |
1035 | 1049 | ||