]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
rbd: handle DISCARD and WRITE_ZEROES separately
authorIlya Dryomov <idryomov@gmail.com>
Tue, 29 Jan 2019 11:46:25 +0000 (12:46 +0100)
committerIlya Dryomov <idryomov@gmail.com>
Tue, 5 Mar 2019 17:55:17 +0000 (18:55 +0100)
With discard_zeroes_data gone in commit 48920ff2a5a9 ("block: remove
the discard_zeroes_data flag"), continuing to provide this guarantee is
pointless: applications can't query it and discards can only be used
for deallocating.

Add OBJ_OP_ZEROOUT and move the existing logic under it.  As the first
step to divorcing OBJ_OP_DISCARD, stop worrying about copyups but keep
special casing whole-object layered discards.

Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Reviewed-by: Jason Dillaman <dillaman@redhat.com>
drivers/block/rbd.c

index d071608507f2b70d718a56e3c9e957cd3b51a533..3ef97121a8f54a3eaf23823247eb0305c095c9c3 100644 (file)
@@ -214,6 +214,7 @@ enum obj_operation_type {
        OBJ_OP_READ = 1,
        OBJ_OP_WRITE,
        OBJ_OP_DISCARD,
+       OBJ_OP_ZEROOUT,
 };
 
 /*
@@ -857,6 +858,8 @@ static char* obj_op_name(enum obj_operation_type op_type)
                return "write";
        case OBJ_OP_DISCARD:
                return "discard";
+       case OBJ_OP_ZEROOUT:
+               return "zeroout";
        default:
                return "???";
        }
@@ -1419,6 +1422,7 @@ static bool rbd_img_is_write(struct rbd_img_request *img_req)
                return false;
        case OBJ_OP_WRITE:
        case OBJ_OP_DISCARD:
+       case OBJ_OP_ZEROOUT:
                return true;
        default:
                BUG();
@@ -1841,7 +1845,40 @@ static int rbd_obj_setup_write(struct rbd_obj_request *obj_req)
        return 0;
 }
 
-static void __rbd_obj_setup_discard(struct rbd_obj_request *obj_req,
+static u16 truncate_or_zero_opcode(struct rbd_obj_request *obj_req)
+{
+       return rbd_obj_is_tail(obj_req) ? CEPH_OSD_OP_TRUNCATE :
+                                         CEPH_OSD_OP_ZERO;
+}
+
+static int rbd_obj_setup_discard(struct rbd_obj_request *obj_req)
+{
+       int ret;
+
+       /* reverse map the entire object onto the parent */
+       ret = rbd_obj_calc_img_extents(obj_req, true);
+       if (ret)
+               return ret;
+
+       obj_req->osd_req = rbd_osd_req_create(obj_req, 1);
+       if (!obj_req->osd_req)
+               return -ENOMEM;
+
+       if (rbd_obj_is_entire(obj_req) && !obj_req->num_img_extents) {
+               osd_req_op_init(obj_req->osd_req, 0, CEPH_OSD_OP_DELETE, 0);
+       } else {
+               osd_req_op_extent_init(obj_req->osd_req, 0,
+                                      truncate_or_zero_opcode(obj_req),
+                                      obj_req->ex.oe_off, obj_req->ex.oe_len,
+                                      0, 0);
+       }
+
+       obj_req->write_state = RBD_OBJ_WRITE_FLAT;
+       rbd_osd_req_format_write(obj_req);
+       return 0;
+}
+
+static void __rbd_obj_setup_zeroout(struct rbd_obj_request *obj_req,
                                    unsigned int which)
 {
        u16 opcode;
@@ -1856,10 +1893,8 @@ static void __rbd_obj_setup_discard(struct rbd_obj_request *obj_req,
                                        CEPH_OSD_OP_DELETE, 0);
                        opcode = 0;
                }
-       } else if (rbd_obj_is_tail(obj_req)) {
-               opcode = CEPH_OSD_OP_TRUNCATE;
        } else {
-               opcode = CEPH_OSD_OP_ZERO;
+               opcode = truncate_or_zero_opcode(obj_req);
        }
 
        if (opcode)
@@ -1871,7 +1906,7 @@ static void __rbd_obj_setup_discard(struct rbd_obj_request *obj_req,
        rbd_osd_req_format_write(obj_req);
 }
 
-static int rbd_obj_setup_discard(struct rbd_obj_request *obj_req)
+static int rbd_obj_setup_zeroout(struct rbd_obj_request *obj_req)
 {
        unsigned int num_osd_ops, which = 0;
        int ret;
@@ -1907,7 +1942,7 @@ static int rbd_obj_setup_discard(struct rbd_obj_request *obj_req)
                        return ret;
        }
 
-       __rbd_obj_setup_discard(obj_req, which);
+       __rbd_obj_setup_zeroout(obj_req, which);
        return 0;
 }
 
@@ -1932,6 +1967,9 @@ static int __rbd_img_fill_request(struct rbd_img_request *img_req)
                case OBJ_OP_DISCARD:
                        ret = rbd_obj_setup_discard(obj_req);
                        break;
+               case OBJ_OP_ZEROOUT:
+                       ret = rbd_obj_setup_zeroout(obj_req);
+                       break;
                default:
                        rbd_assert(0);
                }
@@ -2392,9 +2430,9 @@ static int rbd_obj_issue_copyup(struct rbd_obj_request *obj_req, u32 bytes)
        case OBJ_OP_WRITE:
                __rbd_obj_setup_write(obj_req, 1);
                break;
-       case OBJ_OP_DISCARD:
+       case OBJ_OP_ZEROOUT:
                rbd_assert(!rbd_obj_is_entire(obj_req));
-               __rbd_obj_setup_discard(obj_req, 1);
+               __rbd_obj_setup_zeroout(obj_req, 1);
                break;
        default:
                rbd_assert(0);
@@ -2524,6 +2562,7 @@ static bool __rbd_obj_handle_request(struct rbd_obj_request *obj_req)
        case OBJ_OP_WRITE:
                return rbd_obj_handle_write(obj_req);
        case OBJ_OP_DISCARD:
+       case OBJ_OP_ZEROOUT:
                if (rbd_obj_handle_write(obj_req)) {
                        /*
                         * Hide -ENOENT from delete/truncate/zero -- discarding
@@ -3636,9 +3675,11 @@ static void rbd_queue_workfn(struct work_struct *work)
 
        switch (req_op(rq)) {
        case REQ_OP_DISCARD:
-       case REQ_OP_WRITE_ZEROES:
                op_type = OBJ_OP_DISCARD;
                break;
+       case REQ_OP_WRITE_ZEROES:
+               op_type = OBJ_OP_ZEROOUT;
+               break;
        case REQ_OP_WRITE:
                op_type = OBJ_OP_WRITE;
                break;
@@ -3718,7 +3759,7 @@ static void rbd_queue_workfn(struct work_struct *work)
        img_request->rq = rq;
        snapc = NULL; /* img_request consumes a ref */
 
-       if (op_type == OBJ_OP_DISCARD)
+       if (op_type == OBJ_OP_DISCARD || op_type == OBJ_OP_ZEROOUT)
                result = rbd_img_fill_nodata(img_request, offset, length);
        else
                result = rbd_img_fill_from_bio(img_request, offset, length,