drbd: Create the protocol feature THIN_RESYNC
If thinly provisioned volumes are used, during a resync the sync source tries to find out if a block is deallocated. If it is deallocated, then the resync target uses block_dev_issue_zeroout() on the range in question. 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>
This commit is contained in:

committed by
Jens Axboe

parent
a5ca66c419
commit
92d94ae66a
@@ -165,6 +165,7 @@ struct p_block_req {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define FF_TRIM 1
|
#define FF_TRIM 1
|
||||||
|
#define FF_THIN_RESYNC 2
|
||||||
|
|
||||||
struct p_connection_features {
|
struct p_connection_features {
|
||||||
u32 protocol_min;
|
u32 protocol_min;
|
||||||
|
@@ -48,7 +48,7 @@
|
|||||||
#include "drbd_req.h"
|
#include "drbd_req.h"
|
||||||
#include "drbd_vli.h"
|
#include "drbd_vli.h"
|
||||||
|
|
||||||
#define PRO_FEATURES (FF_TRIM)
|
#define PRO_FEATURES (FF_TRIM | FF_THIN_RESYNC)
|
||||||
|
|
||||||
struct packet_info {
|
struct packet_info {
|
||||||
enum drbd_packet cmd;
|
enum drbd_packet cmd;
|
||||||
@@ -4991,6 +4991,9 @@ static int drbd_do_features(struct drbd_connection *connection)
|
|||||||
drbd_info(connection, "Agreed to%ssupport TRIM on protocol level\n",
|
drbd_info(connection, "Agreed to%ssupport TRIM on protocol level\n",
|
||||||
connection->agreed_features & FF_TRIM ? " " : " not ");
|
connection->agreed_features & FF_TRIM ? " " : " not ");
|
||||||
|
|
||||||
|
drbd_info(connection, "Agreed to%ssupport THIN_RESYNC on protocol level\n",
|
||||||
|
connection->agreed_features & FF_THIN_RESYNC ? " " : " not ");
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
incompat:
|
incompat:
|
||||||
|
@@ -583,6 +583,7 @@ static int make_resync_request(struct drbd_device *const device, int cancel)
|
|||||||
int number, rollback_i, size;
|
int number, rollback_i, size;
|
||||||
int align, requeue = 0;
|
int align, requeue = 0;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
int discard_granularity = 0;
|
||||||
|
|
||||||
if (unlikely(cancel))
|
if (unlikely(cancel))
|
||||||
return 0;
|
return 0;
|
||||||
@@ -602,6 +603,12 @@ static int make_resync_request(struct drbd_device *const device, int cancel)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (connection->agreed_features & FF_THIN_RESYNC) {
|
||||||
|
rcu_read_lock();
|
||||||
|
discard_granularity = rcu_dereference(device->ldev->disk_conf)->rs_discard_granularity;
|
||||||
|
rcu_read_unlock();
|
||||||
|
}
|
||||||
|
|
||||||
max_bio_size = queue_max_hw_sectors(device->rq_queue) << 9;
|
max_bio_size = queue_max_hw_sectors(device->rq_queue) << 9;
|
||||||
number = drbd_rs_number_requests(device);
|
number = drbd_rs_number_requests(device);
|
||||||
if (number <= 0)
|
if (number <= 0)
|
||||||
@@ -666,6 +673,9 @@ next_sector:
|
|||||||
if (sector & ((1<<(align+3))-1))
|
if (sector & ((1<<(align+3))-1))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
if (discard_granularity && size == discard_granularity)
|
||||||
|
break;
|
||||||
|
|
||||||
/* do not cross extent boundaries */
|
/* do not cross extent boundaries */
|
||||||
if (((bit+1) & BM_BLOCKS_PER_BM_EXT_MASK) == 0)
|
if (((bit+1) & BM_BLOCKS_PER_BM_EXT_MASK) == 0)
|
||||||
break;
|
break;
|
||||||
@@ -712,7 +722,8 @@ next_sector:
|
|||||||
int err;
|
int err;
|
||||||
|
|
||||||
inc_rs_pending(device);
|
inc_rs_pending(device);
|
||||||
err = drbd_send_drequest(peer_device, P_RS_DATA_REQUEST,
|
err = drbd_send_drequest(peer_device,
|
||||||
|
size == discard_granularity ? P_RS_THIN_REQ : P_RS_DATA_REQUEST,
|
||||||
sector, size, ID_SYNCER);
|
sector, size, ID_SYNCER);
|
||||||
if (err) {
|
if (err) {
|
||||||
drbd_err(device, "drbd_send_drequest() failed, aborting...\n");
|
drbd_err(device, "drbd_send_drequest() failed, aborting...\n");
|
||||||
|
Reference in New Issue
Block a user