Loading drivers/block/drbd/drbd_actlog.c +6 −4 Original line number Diff line number Diff line Loading @@ -1007,22 +1007,22 @@ void __drbd_set_in_sync(struct drbd_conf *mdev, sector_t sector, int size, * called by tl_clear and drbd_send_dblock (==drbd_make_request). * so this can be _any_ process. */ void __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, int size, int __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, int size, const char *file, const unsigned int line) { unsigned long sbnr, ebnr, lbnr, flags; sector_t esector, nr_sectors; unsigned int enr, count; unsigned int enr, count = 0; struct lc_element *e; if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_BIO_SIZE) { dev_err(DEV, "sector: %llus, size: %d\n", (unsigned long long)sector, size); return; return 0; } if (!get_ldev(mdev)) return; /* no disk, no metadata, no bitmap to set bits in */ return 0; /* no disk, no metadata, no bitmap to set bits in */ nr_sectors = drbd_get_capacity(mdev->this_bdev); esector = sector + (size >> 9) - 1; Loading Loading @@ -1052,6 +1052,8 @@ void __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, int size, out: put_ldev(mdev); return count; } static Loading drivers/block/drbd/drbd_int.h +13 −1 Original line number Diff line number Diff line Loading @@ -212,6 +212,7 @@ enum drbd_packets { /* P_CKPT_FENCE_REQ = 0x25, * currently reserved for protocol D */ /* P_CKPT_DISABLE_REQ = 0x26, * currently reserved for protocol D */ P_DELAY_PROBE = 0x27, /* is used on BOTH sockets */ P_OUT_OF_SYNC = 0x28, /* Mark as out of sync (Outrunning), data socket */ P_MAX_CMD = 0x28, P_MAY_IGNORE = 0x100, /* Flag to test if (cmd > P_MAY_IGNORE) ... */ Loading Loading @@ -269,6 +270,7 @@ static inline const char *cmdname(enum drbd_packets cmd) [P_RS_IS_IN_SYNC] = "CsumRSIsInSync", [P_COMPRESSED_BITMAP] = "CBitmap", [P_DELAY_PROBE] = "DelayProbe", [P_OUT_OF_SYNC] = "OutOfSync", [P_MAX_CMD] = NULL, }; Loading Loading @@ -550,6 +552,13 @@ struct p_discard { u32 pad; } __packed; struct p_block_desc { struct p_header80 head; u64 sector; u32 blksize; u32 pad; /* to multiple of 8 Byte */ } __packed; /* Valid values for the encoding field. * Bump proto version when changing this. */ enum drbd_bitmap_code { Loading Loading @@ -647,6 +656,7 @@ union p_polymorph { struct p_block_req block_req; struct p_delay_probe93 delay_probe93; struct p_rs_uuid rs_uuid; struct p_block_desc block_desc; } __packed; /**********************************************************************/ Loading Loading @@ -1221,6 +1231,7 @@ extern int drbd_send_ack_dp(struct drbd_conf *mdev, enum drbd_packets cmd, struct p_data *dp, int data_size); extern int drbd_send_ack_ex(struct drbd_conf *mdev, enum drbd_packets cmd, sector_t sector, int blksize, u64 block_id); extern int drbd_send_oos(struct drbd_conf *mdev, struct drbd_request *req); extern int drbd_send_block(struct drbd_conf *mdev, enum drbd_packets cmd, struct drbd_epoch_entry *e); extern int drbd_send_dblock(struct drbd_conf *mdev, struct drbd_request *req); Loading Loading @@ -1534,6 +1545,7 @@ extern int w_send_read_req(struct drbd_conf *, struct drbd_work *, int); extern int w_prev_work_done(struct drbd_conf *, struct drbd_work *, int); extern int w_e_reissue(struct drbd_conf *, struct drbd_work *, int); extern int w_restart_disk_io(struct drbd_conf *, struct drbd_work *, int); extern int w_send_oos(struct drbd_conf *, struct drbd_work *, int); extern void resync_timer_fn(unsigned long data); Loading Loading @@ -1626,7 +1638,7 @@ extern void __drbd_set_in_sync(struct drbd_conf *mdev, sector_t sector, int size, const char *file, const unsigned int line); #define drbd_set_in_sync(mdev, sector, size) \ __drbd_set_in_sync(mdev, sector, size, __FILE__, __LINE__) extern void __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, extern int __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, int size, const char *file, const unsigned int line); #define drbd_set_out_of_sync(mdev, sector, size) \ __drbd_set_out_of_sync(mdev, sector, size, __FILE__, __LINE__) Loading drivers/block/drbd/drbd_main.c +10 −0 Original line number Diff line number Diff line Loading @@ -2634,6 +2634,16 @@ int drbd_send_block(struct drbd_conf *mdev, enum drbd_packets cmd, return ok; } int drbd_send_oos(struct drbd_conf *mdev, struct drbd_request *req) { struct p_block_desc p; p.sector = cpu_to_be64(req->sector); p.blksize = cpu_to_be32(req->size); return drbd_send_cmd(mdev, USE_DATA_SOCKET, P_OUT_OF_SYNC, &p.head, sizeof(p)); } /* drbd_send distinguishes two cases: Loading drivers/block/drbd/drbd_receiver.c +10 −0 Original line number Diff line number Diff line Loading @@ -3562,6 +3562,15 @@ static int receive_UnplugRemote(struct drbd_conf *mdev, enum drbd_packets cmd, u return TRUE; } static int receive_out_of_sync(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size) { struct p_block_desc *p = &mdev->data.rbuf.block_desc; drbd_set_out_of_sync(mdev, be64_to_cpu(p->sector), be32_to_cpu(p->blksize)); return TRUE; } typedef int (*drbd_cmd_handler_f)(struct drbd_conf *, enum drbd_packets cmd, unsigned int to_receive); struct data_cmd { Loading Loading @@ -3592,6 +3601,7 @@ static struct data_cmd drbd_cmd_handler[] = { [P_OV_REPLY] = { 1, sizeof(struct p_block_req), receive_DataRequest }, [P_CSUM_RS_REQUEST] = { 1, sizeof(struct p_block_req), receive_DataRequest }, [P_DELAY_PROBE] = { 0, sizeof(struct p_delay_probe93), receive_skip }, [P_OUT_OF_SYNC] = { 0, sizeof(struct p_block_desc), receive_out_of_sync }, /* anything missing from this table is in * the asender_tbl, see get_asender_cmd */ [P_MAX_CMD] = { 0, 0, NULL }, Loading drivers/block/drbd/drbd_req.c +32 −12 Original line number Diff line number Diff line Loading @@ -142,7 +142,7 @@ static void _about_to_complete_local_write(struct drbd_conf *mdev, /* before we can signal completion to the upper layers, * we may need to close the current epoch */ if (mdev->state.conn >= C_CONNECTED && if (mdev->state.conn >= C_CONNECTED && mdev->state.conn < C_AHEAD && req->epoch == mdev->newest_tle->br_number) queue_barrier(mdev); Loading Loading @@ -545,6 +545,14 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what, break; case queue_for_send_oos: req->rq_state |= RQ_NET_QUEUED; req->w.cb = w_send_oos; drbd_queue_work(&mdev->data.work, &req->w); break; case oos_handed_to_network: /* actually the same */ case send_canceled: /* treat it the same */ case send_failed: Loading Loading @@ -756,7 +764,7 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio) const sector_t sector = bio->bi_sector; struct drbd_tl_epoch *b = NULL; struct drbd_request *req; int local, remote; int local, remote, send_oos = 0; int err = -EIO; int ret = 0; Loading Loading @@ -820,8 +828,11 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio) } remote = remote && (mdev->state.pdsk == D_UP_TO_DATE || (mdev->state.pdsk == D_INCONSISTENT && mdev->state.conn >= C_CONNECTED)); (mdev->state.pdsk >= D_INCONSISTENT && mdev->state.conn >= C_CONNECTED && mdev->state.conn < C_AHEAD)); send_oos = (rw == WRITE && mdev->state.conn == C_AHEAD && mdev->state.pdsk >= D_INCONSISTENT); if (!(local || remote) && !is_susp(mdev->state)) { if (__ratelimit(&drbd_ratelimit_state)) Loading @@ -835,7 +846,7 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio) * but there is a race between testing the bit and pointer outside the * spinlock, and grabbing the spinlock. * if we lost that race, we retry. */ if (rw == WRITE && remote && if (rw == WRITE && (remote || send_oos) && mdev->unused_spare_tle == NULL && test_bit(CREATE_BARRIER, &mdev->flags)) { allocate_barrier: Loading @@ -860,11 +871,15 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio) goto fail_free_complete; } if (remote) { if (remote || send_oos) { remote = (mdev->state.pdsk == D_UP_TO_DATE || (mdev->state.pdsk == D_INCONSISTENT && mdev->state.conn >= C_CONNECTED)); if (!remote) (mdev->state.pdsk >= D_INCONSISTENT && mdev->state.conn >= C_CONNECTED && mdev->state.conn < C_AHEAD)); send_oos = (rw == WRITE && mdev->state.conn == C_AHEAD && mdev->state.pdsk >= D_INCONSISTENT); if (!(remote || send_oos)) dev_warn(DEV, "lost connection while grabbing the req_lock!\n"); if (!(local || remote)) { dev_err(DEV, "IO ERROR: neither local nor remote disk\n"); Loading @@ -877,7 +892,7 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio) mdev->unused_spare_tle = b; b = NULL; } if (rw == WRITE && remote && if (rw == WRITE && (remote || send_oos) && mdev->unused_spare_tle == NULL && test_bit(CREATE_BARRIER, &mdev->flags)) { /* someone closed the current epoch Loading @@ -900,7 +915,7 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio) * barrier packet. To get the write ordering right, we only have to * make sure that, if this is a write request and it triggered a * barrier packet, this request is queued within the same spinlock. */ if (remote && mdev->unused_spare_tle && if ((remote || send_oos) && mdev->unused_spare_tle && test_and_clear_bit(CREATE_BARRIER, &mdev->flags)) { _tl_add_barrier(mdev, mdev->unused_spare_tle); mdev->unused_spare_tle = NULL; Loading Loading @@ -948,8 +963,11 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio) ? queue_for_net_write : queue_for_net_read); } if (send_oos && drbd_set_out_of_sync(mdev, sector, size)) _req_mod(req, queue_for_send_oos); if (remote && mdev->net_conf->on_congestion != OC_BLOCK) { if (remote && mdev->net_conf->on_congestion != OC_BLOCK && mdev->agreed_pro_version >= 96) { int congested = 0; if (mdev->net_conf->cong_fill && Loading @@ -964,6 +982,8 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio) } if (congested) { queue_barrier(mdev); if (mdev->net_conf->on_congestion == OC_PULL_AHEAD) _drbd_set_state(_NS(mdev, conn, C_AHEAD), 0, NULL); else /*mdev->net_conf->on_congestion == OC_DISCONNECT */ Loading Loading
drivers/block/drbd/drbd_actlog.c +6 −4 Original line number Diff line number Diff line Loading @@ -1007,22 +1007,22 @@ void __drbd_set_in_sync(struct drbd_conf *mdev, sector_t sector, int size, * called by tl_clear and drbd_send_dblock (==drbd_make_request). * so this can be _any_ process. */ void __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, int size, int __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, int size, const char *file, const unsigned int line) { unsigned long sbnr, ebnr, lbnr, flags; sector_t esector, nr_sectors; unsigned int enr, count; unsigned int enr, count = 0; struct lc_element *e; if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_BIO_SIZE) { dev_err(DEV, "sector: %llus, size: %d\n", (unsigned long long)sector, size); return; return 0; } if (!get_ldev(mdev)) return; /* no disk, no metadata, no bitmap to set bits in */ return 0; /* no disk, no metadata, no bitmap to set bits in */ nr_sectors = drbd_get_capacity(mdev->this_bdev); esector = sector + (size >> 9) - 1; Loading Loading @@ -1052,6 +1052,8 @@ void __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, int size, out: put_ldev(mdev); return count; } static Loading
drivers/block/drbd/drbd_int.h +13 −1 Original line number Diff line number Diff line Loading @@ -212,6 +212,7 @@ enum drbd_packets { /* P_CKPT_FENCE_REQ = 0x25, * currently reserved for protocol D */ /* P_CKPT_DISABLE_REQ = 0x26, * currently reserved for protocol D */ P_DELAY_PROBE = 0x27, /* is used on BOTH sockets */ P_OUT_OF_SYNC = 0x28, /* Mark as out of sync (Outrunning), data socket */ P_MAX_CMD = 0x28, P_MAY_IGNORE = 0x100, /* Flag to test if (cmd > P_MAY_IGNORE) ... */ Loading Loading @@ -269,6 +270,7 @@ static inline const char *cmdname(enum drbd_packets cmd) [P_RS_IS_IN_SYNC] = "CsumRSIsInSync", [P_COMPRESSED_BITMAP] = "CBitmap", [P_DELAY_PROBE] = "DelayProbe", [P_OUT_OF_SYNC] = "OutOfSync", [P_MAX_CMD] = NULL, }; Loading Loading @@ -550,6 +552,13 @@ struct p_discard { u32 pad; } __packed; struct p_block_desc { struct p_header80 head; u64 sector; u32 blksize; u32 pad; /* to multiple of 8 Byte */ } __packed; /* Valid values for the encoding field. * Bump proto version when changing this. */ enum drbd_bitmap_code { Loading Loading @@ -647,6 +656,7 @@ union p_polymorph { struct p_block_req block_req; struct p_delay_probe93 delay_probe93; struct p_rs_uuid rs_uuid; struct p_block_desc block_desc; } __packed; /**********************************************************************/ Loading Loading @@ -1221,6 +1231,7 @@ extern int drbd_send_ack_dp(struct drbd_conf *mdev, enum drbd_packets cmd, struct p_data *dp, int data_size); extern int drbd_send_ack_ex(struct drbd_conf *mdev, enum drbd_packets cmd, sector_t sector, int blksize, u64 block_id); extern int drbd_send_oos(struct drbd_conf *mdev, struct drbd_request *req); extern int drbd_send_block(struct drbd_conf *mdev, enum drbd_packets cmd, struct drbd_epoch_entry *e); extern int drbd_send_dblock(struct drbd_conf *mdev, struct drbd_request *req); Loading Loading @@ -1534,6 +1545,7 @@ extern int w_send_read_req(struct drbd_conf *, struct drbd_work *, int); extern int w_prev_work_done(struct drbd_conf *, struct drbd_work *, int); extern int w_e_reissue(struct drbd_conf *, struct drbd_work *, int); extern int w_restart_disk_io(struct drbd_conf *, struct drbd_work *, int); extern int w_send_oos(struct drbd_conf *, struct drbd_work *, int); extern void resync_timer_fn(unsigned long data); Loading Loading @@ -1626,7 +1638,7 @@ extern void __drbd_set_in_sync(struct drbd_conf *mdev, sector_t sector, int size, const char *file, const unsigned int line); #define drbd_set_in_sync(mdev, sector, size) \ __drbd_set_in_sync(mdev, sector, size, __FILE__, __LINE__) extern void __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, extern int __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, int size, const char *file, const unsigned int line); #define drbd_set_out_of_sync(mdev, sector, size) \ __drbd_set_out_of_sync(mdev, sector, size, __FILE__, __LINE__) Loading
drivers/block/drbd/drbd_main.c +10 −0 Original line number Diff line number Diff line Loading @@ -2634,6 +2634,16 @@ int drbd_send_block(struct drbd_conf *mdev, enum drbd_packets cmd, return ok; } int drbd_send_oos(struct drbd_conf *mdev, struct drbd_request *req) { struct p_block_desc p; p.sector = cpu_to_be64(req->sector); p.blksize = cpu_to_be32(req->size); return drbd_send_cmd(mdev, USE_DATA_SOCKET, P_OUT_OF_SYNC, &p.head, sizeof(p)); } /* drbd_send distinguishes two cases: Loading
drivers/block/drbd/drbd_receiver.c +10 −0 Original line number Diff line number Diff line Loading @@ -3562,6 +3562,15 @@ static int receive_UnplugRemote(struct drbd_conf *mdev, enum drbd_packets cmd, u return TRUE; } static int receive_out_of_sync(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size) { struct p_block_desc *p = &mdev->data.rbuf.block_desc; drbd_set_out_of_sync(mdev, be64_to_cpu(p->sector), be32_to_cpu(p->blksize)); return TRUE; } typedef int (*drbd_cmd_handler_f)(struct drbd_conf *, enum drbd_packets cmd, unsigned int to_receive); struct data_cmd { Loading Loading @@ -3592,6 +3601,7 @@ static struct data_cmd drbd_cmd_handler[] = { [P_OV_REPLY] = { 1, sizeof(struct p_block_req), receive_DataRequest }, [P_CSUM_RS_REQUEST] = { 1, sizeof(struct p_block_req), receive_DataRequest }, [P_DELAY_PROBE] = { 0, sizeof(struct p_delay_probe93), receive_skip }, [P_OUT_OF_SYNC] = { 0, sizeof(struct p_block_desc), receive_out_of_sync }, /* anything missing from this table is in * the asender_tbl, see get_asender_cmd */ [P_MAX_CMD] = { 0, 0, NULL }, Loading
drivers/block/drbd/drbd_req.c +32 −12 Original line number Diff line number Diff line Loading @@ -142,7 +142,7 @@ static void _about_to_complete_local_write(struct drbd_conf *mdev, /* before we can signal completion to the upper layers, * we may need to close the current epoch */ if (mdev->state.conn >= C_CONNECTED && if (mdev->state.conn >= C_CONNECTED && mdev->state.conn < C_AHEAD && req->epoch == mdev->newest_tle->br_number) queue_barrier(mdev); Loading Loading @@ -545,6 +545,14 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what, break; case queue_for_send_oos: req->rq_state |= RQ_NET_QUEUED; req->w.cb = w_send_oos; drbd_queue_work(&mdev->data.work, &req->w); break; case oos_handed_to_network: /* actually the same */ case send_canceled: /* treat it the same */ case send_failed: Loading Loading @@ -756,7 +764,7 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio) const sector_t sector = bio->bi_sector; struct drbd_tl_epoch *b = NULL; struct drbd_request *req; int local, remote; int local, remote, send_oos = 0; int err = -EIO; int ret = 0; Loading Loading @@ -820,8 +828,11 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio) } remote = remote && (mdev->state.pdsk == D_UP_TO_DATE || (mdev->state.pdsk == D_INCONSISTENT && mdev->state.conn >= C_CONNECTED)); (mdev->state.pdsk >= D_INCONSISTENT && mdev->state.conn >= C_CONNECTED && mdev->state.conn < C_AHEAD)); send_oos = (rw == WRITE && mdev->state.conn == C_AHEAD && mdev->state.pdsk >= D_INCONSISTENT); if (!(local || remote) && !is_susp(mdev->state)) { if (__ratelimit(&drbd_ratelimit_state)) Loading @@ -835,7 +846,7 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio) * but there is a race between testing the bit and pointer outside the * spinlock, and grabbing the spinlock. * if we lost that race, we retry. */ if (rw == WRITE && remote && if (rw == WRITE && (remote || send_oos) && mdev->unused_spare_tle == NULL && test_bit(CREATE_BARRIER, &mdev->flags)) { allocate_barrier: Loading @@ -860,11 +871,15 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio) goto fail_free_complete; } if (remote) { if (remote || send_oos) { remote = (mdev->state.pdsk == D_UP_TO_DATE || (mdev->state.pdsk == D_INCONSISTENT && mdev->state.conn >= C_CONNECTED)); if (!remote) (mdev->state.pdsk >= D_INCONSISTENT && mdev->state.conn >= C_CONNECTED && mdev->state.conn < C_AHEAD)); send_oos = (rw == WRITE && mdev->state.conn == C_AHEAD && mdev->state.pdsk >= D_INCONSISTENT); if (!(remote || send_oos)) dev_warn(DEV, "lost connection while grabbing the req_lock!\n"); if (!(local || remote)) { dev_err(DEV, "IO ERROR: neither local nor remote disk\n"); Loading @@ -877,7 +892,7 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio) mdev->unused_spare_tle = b; b = NULL; } if (rw == WRITE && remote && if (rw == WRITE && (remote || send_oos) && mdev->unused_spare_tle == NULL && test_bit(CREATE_BARRIER, &mdev->flags)) { /* someone closed the current epoch Loading @@ -900,7 +915,7 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio) * barrier packet. To get the write ordering right, we only have to * make sure that, if this is a write request and it triggered a * barrier packet, this request is queued within the same spinlock. */ if (remote && mdev->unused_spare_tle && if ((remote || send_oos) && mdev->unused_spare_tle && test_and_clear_bit(CREATE_BARRIER, &mdev->flags)) { _tl_add_barrier(mdev, mdev->unused_spare_tle); mdev->unused_spare_tle = NULL; Loading Loading @@ -948,8 +963,11 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio) ? queue_for_net_write : queue_for_net_read); } if (send_oos && drbd_set_out_of_sync(mdev, sector, size)) _req_mod(req, queue_for_send_oos); if (remote && mdev->net_conf->on_congestion != OC_BLOCK) { if (remote && mdev->net_conf->on_congestion != OC_BLOCK && mdev->agreed_pro_version >= 96) { int congested = 0; if (mdev->net_conf->cong_fill && Loading @@ -964,6 +982,8 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio) } if (congested) { queue_barrier(mdev); if (mdev->net_conf->on_congestion == OC_PULL_AHEAD) _drbd_set_state(_NS(mdev, conn, C_AHEAD), 0, NULL); else /*mdev->net_conf->on_congestion == OC_DISCONNECT */ Loading