drbd: prepare sending side for REQ_DISCARD
authorLars Ellenberg <lars.ellenberg@linbit.com>
Mon, 28 Apr 2014 16:43:24 +0000 (18:43 +0200)
committerJens Axboe <axboe@fb.com>
Wed, 30 Apr 2014 19:46:55 +0000 (13:46 -0600)
Note that I do NOT call __drbd_chk_io_error for failed REQ_DISCARD.
That may be wrong, though, or needs to differ between EOPNOTSUPP and
other errors...

Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
drivers/block/drbd/drbd_main.c
drivers/block/drbd/drbd_req.c
drivers/block/drbd/drbd_req.h
drivers/block/drbd/drbd_worker.c

index 05db597401e6369dd90fd0f64ffaa7d982c8a136..960645c26e6fc1b107e0db1ae016fd15800d3514 100644 (file)
@@ -1607,8 +1607,8 @@ static u32 bio_flags_to_wire(struct drbd_connection *connection, unsigned long b
                return bi_rw & REQ_SYNC ? DP_RW_SYNC : 0;
 }
 
-/* Used to send write requests
- * R_PRIMARY -> Peer   (P_DATA)
+/* Used to send write or TRIM aka REQ_DISCARD requests
+ * R_PRIMARY -> Peer   (P_DATA, P_TRIM)
  */
 int drbd_send_dblock(struct drbd_peer_device *peer_device, struct drbd_request *req)
 {
@@ -1640,6 +1640,16 @@ int drbd_send_dblock(struct drbd_peer_device *peer_device, struct drbd_request *
                        dp_flags |= DP_SEND_WRITE_ACK;
        }
        p->dp_flags = cpu_to_be32(dp_flags);
+
+       if (dp_flags & DP_DISCARD) {
+               struct p_trim *t = (struct p_trim*)p;
+               t->size = cpu_to_be32(req->i.size);
+               err = __send_command(peer_device->connection, device->vnr, sock, P_TRIM, sizeof(*t), NULL, 0);
+               goto out;
+       }
+
+       /* our digest is still only over the payload.
+        * TRIM does not carry any payload. */
        if (dgs)
                drbd_csum_bio(peer_device->connection->integrity_tfm, req->master_bio, p + 1);
        err = __send_command(peer_device->connection, device->vnr, sock, P_DATA, sizeof(*p) + dgs, NULL, req->i.size);
@@ -1675,6 +1685,7 @@ int drbd_send_dblock(struct drbd_peer_device *peer_device, struct drbd_request *
                     ... Be noisy about digest too large ...
                } */
        }
+out:
        mutex_unlock(&sock->mutex);  /* locked by drbd_prepare_command() */
 
        return err;
index 3779c8d2875bb00529853e1e2c4d6f6a5a083b17..7aadd0906b015371b2106d111ca682359f6a170c 100644 (file)
@@ -522,6 +522,13 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
                mod_rq_state(req, m, RQ_LOCAL_PENDING, RQ_LOCAL_COMPLETED);
                break;
 
+       case DISCARD_COMPLETED_NOTSUPP:
+       case DISCARD_COMPLETED_WITH_ERROR:
+               /* I'd rather not detach from local disk just because it
+                * failed a REQ_DISCARD. */
+               mod_rq_state(req, m, RQ_LOCAL_PENDING, RQ_LOCAL_COMPLETED);
+               break;
+
        case QUEUE_FOR_NET_READ:
                /* READ or READA, and
                 * no local disk,
index 07cc8e8a6e2a3e5701fa65947f820ce8d36ac739..8566cd5866b4e2388cdb441439f25eecf6071443 100644 (file)
@@ -110,11 +110,14 @@ enum drbd_req_event {
        BARRIER_ACKED, /* in protocol A and B */
        DATA_RECEIVED, /* (remote read) */
 
+       COMPLETED_OK,
        READ_COMPLETED_WITH_ERROR,
        READ_AHEAD_COMPLETED_WITH_ERROR,
        WRITE_COMPLETED_WITH_ERROR,
+       DISCARD_COMPLETED_NOTSUPP,
+       DISCARD_COMPLETED_WITH_ERROR,
+
        ABORT_DISK_IO,
-       COMPLETED_OK,
        RESEND,
        FAIL_FROZEN_DISK_IO,
        RESTART_FROZEN_DISK_IO,
index 5fd4eaee49bcace7a11653c3d467f95db43a8861..26338bedb25b71cb67e8bd342e8b8d05c7862252 100644 (file)
@@ -267,7 +267,12 @@ void drbd_request_endio(struct bio *bio, int error)
 
        /* to avoid recursion in __req_mod */
        if (unlikely(error)) {
-               what = (bio_data_dir(bio) == WRITE)
+               if (bio->bi_rw & REQ_DISCARD)
+                       what = (error == -EOPNOTSUPP)
+                               ? DISCARD_COMPLETED_NOTSUPP
+                               : DISCARD_COMPLETED_WITH_ERROR;
+               else
+                       what = (bio_data_dir(bio) == WRITE)
                        ? WRITE_COMPLETED_WITH_ERROR
                        : (bio_rw(bio) == READ)
                          ? READ_COMPLETED_WITH_ERROR
This page took 0.029184 seconds and 5 git commands to generate.