diff options
author | Alex Elder <elder@inktank.com> | 2013-02-06 00:41:50 -0500 |
---|---|---|
committer | Sage Weil <sage@inktank.com> | 2013-02-13 21:29:11 -0500 |
commit | 077413082f9ade9ca4d9774dbdc81ee7256d8089 (patch) | |
tree | 825678f1ad0b9108bb2beb7e6f1e29415d49d27c /drivers/block | |
parent | a14ea269dd6b5e48a2941ba73b202cd7cd5d716d (diff) |
rbd: add barriers near done flag operations
Somehow, I missed this little item in Documentation/atomic_ops.txt:
*** WARNING: atomic_read() and atomic_set() DO NOT IMPLY BARRIERS! ***
Create and use some helper functions that include the proper memory
barriers for manipulating the done field.
Signed-off-by: Alex Elder <elder@inktank.com>
Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/rbd.c | 30 |
1 files changed, 24 insertions, 6 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 91983a60487b..982963ec2607 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c | |||
@@ -1216,10 +1216,28 @@ static int rbd_obj_request_wait(struct rbd_obj_request *obj_request) | |||
1216 | return wait_for_completion_interruptible(&obj_request->completion); | 1216 | return wait_for_completion_interruptible(&obj_request->completion); |
1217 | } | 1217 | } |
1218 | 1218 | ||
1219 | static void obj_request_done_init(struct rbd_obj_request *obj_request) | ||
1220 | { | ||
1221 | atomic_set(&obj_request->done, 0); | ||
1222 | smp_wmb(); | ||
1223 | } | ||
1224 | |||
1225 | static void obj_request_done_set(struct rbd_obj_request *obj_request) | ||
1226 | { | ||
1227 | atomic_set(&obj_request->done, 1); | ||
1228 | smp_wmb(); | ||
1229 | } | ||
1230 | |||
1231 | static bool obj_request_done_test(struct rbd_obj_request *obj_request) | ||
1232 | { | ||
1233 | smp_rmb(); | ||
1234 | return atomic_read(&obj_request->done) != 0; | ||
1235 | } | ||
1236 | |||
1219 | static void rbd_osd_trivial_callback(struct rbd_obj_request *obj_request, | 1237 | static void rbd_osd_trivial_callback(struct rbd_obj_request *obj_request, |
1220 | struct ceph_osd_op *op) | 1238 | struct ceph_osd_op *op) |
1221 | { | 1239 | { |
1222 | atomic_set(&obj_request->done, 1); | 1240 | obj_request_done_set(obj_request); |
1223 | } | 1241 | } |
1224 | 1242 | ||
1225 | static void rbd_obj_request_complete(struct rbd_obj_request *obj_request) | 1243 | static void rbd_obj_request_complete(struct rbd_obj_request *obj_request) |
@@ -1249,14 +1267,14 @@ static void rbd_osd_read_callback(struct rbd_obj_request *obj_request, | |||
1249 | xferred = obj_request->length; | 1267 | xferred = obj_request->length; |
1250 | } | 1268 | } |
1251 | obj_request->xferred = xferred; | 1269 | obj_request->xferred = xferred; |
1252 | atomic_set(&obj_request->done, 1); | 1270 | obj_request_done_set(obj_request); |
1253 | } | 1271 | } |
1254 | 1272 | ||
1255 | static void rbd_osd_write_callback(struct rbd_obj_request *obj_request, | 1273 | static void rbd_osd_write_callback(struct rbd_obj_request *obj_request, |
1256 | struct ceph_osd_op *op) | 1274 | struct ceph_osd_op *op) |
1257 | { | 1275 | { |
1258 | obj_request->xferred = le64_to_cpu(op->extent.length); | 1276 | obj_request->xferred = le64_to_cpu(op->extent.length); |
1259 | atomic_set(&obj_request->done, 1); | 1277 | obj_request_done_set(obj_request); |
1260 | } | 1278 | } |
1261 | 1279 | ||
1262 | static void rbd_osd_req_callback(struct ceph_osd_request *osd_req, | 1280 | static void rbd_osd_req_callback(struct ceph_osd_request *osd_req, |
@@ -1300,7 +1318,7 @@ static void rbd_osd_req_callback(struct ceph_osd_request *osd_req, | |||
1300 | break; | 1318 | break; |
1301 | } | 1319 | } |
1302 | 1320 | ||
1303 | if (atomic_read(&obj_request->done)) | 1321 | if (obj_request_done_test(obj_request)) |
1304 | rbd_obj_request_complete(obj_request); | 1322 | rbd_obj_request_complete(obj_request); |
1305 | } | 1323 | } |
1306 | 1324 | ||
@@ -1407,7 +1425,7 @@ static struct rbd_obj_request *rbd_obj_request_create(const char *object_name, | |||
1407 | obj_request->which = BAD_WHICH; | 1425 | obj_request->which = BAD_WHICH; |
1408 | obj_request->type = type; | 1426 | obj_request->type = type; |
1409 | INIT_LIST_HEAD(&obj_request->links); | 1427 | INIT_LIST_HEAD(&obj_request->links); |
1410 | atomic_set(&obj_request->done, 0); | 1428 | obj_request_done_init(obj_request); |
1411 | init_completion(&obj_request->completion); | 1429 | init_completion(&obj_request->completion); |
1412 | kref_init(&obj_request->kref); | 1430 | kref_init(&obj_request->kref); |
1413 | 1431 | ||
@@ -1611,7 +1629,7 @@ static void rbd_img_obj_callback(struct rbd_obj_request *obj_request) | |||
1611 | rbd_assert(more); | 1629 | rbd_assert(more); |
1612 | rbd_assert(which < img_request->obj_request_count); | 1630 | rbd_assert(which < img_request->obj_request_count); |
1613 | 1631 | ||
1614 | if (!atomic_read(&obj_request->done)) | 1632 | if (!obj_request_done_test(obj_request)) |
1615 | break; | 1633 | break; |
1616 | 1634 | ||
1617 | rbd_assert(obj_request->xferred <= (u64) UINT_MAX); | 1635 | rbd_assert(obj_request->xferred <= (u64) UINT_MAX); |