mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-15 02:05:33 +00:00
drbd: fix null pointer dereference with on-congestion policy when diskless
We must not look at mdev->actlog, unless we have a get_ldev() reference. It also does not make much sense to try to disconnect or pull-ahead of the peer, if we don't have good local data. Only even consider congestion policies, if our local disk is D_UP_TO_DATE. Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com> Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
This commit is contained in:
parent
27012382bc
commit
3b9ef85e05
@ -823,7 +823,7 @@ static void complete_conflicting_writes(struct drbd_request *req)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* called within req_lock and rcu_read_lock() */
|
/* called within req_lock and rcu_read_lock() */
|
||||||
static bool conn_check_congested(struct drbd_conf *mdev)
|
static void maybe_pull_ahead(struct drbd_conf *mdev)
|
||||||
{
|
{
|
||||||
struct drbd_tconn *tconn = mdev->tconn;
|
struct drbd_tconn *tconn = mdev->tconn;
|
||||||
struct net_conf *nc;
|
struct net_conf *nc;
|
||||||
@ -834,7 +834,14 @@ static bool conn_check_congested(struct drbd_conf *mdev)
|
|||||||
on_congestion = nc ? nc->on_congestion : OC_BLOCK;
|
on_congestion = nc ? nc->on_congestion : OC_BLOCK;
|
||||||
if (on_congestion == OC_BLOCK ||
|
if (on_congestion == OC_BLOCK ||
|
||||||
tconn->agreed_pro_version < 96)
|
tconn->agreed_pro_version < 96)
|
||||||
return false;
|
return;
|
||||||
|
|
||||||
|
/* If I don't even have good local storage, we can not reasonably try
|
||||||
|
* to pull ahead of the peer. We also need the local reference to make
|
||||||
|
* sure mdev->act_log is there.
|
||||||
|
*/
|
||||||
|
if (!get_ldev_if_state(mdev, D_UP_TO_DATE))
|
||||||
|
return;
|
||||||
|
|
||||||
if (nc->cong_fill &&
|
if (nc->cong_fill &&
|
||||||
atomic_read(&mdev->ap_in_flight) >= nc->cong_fill) {
|
atomic_read(&mdev->ap_in_flight) >= nc->cong_fill) {
|
||||||
@ -857,8 +864,7 @@ static bool conn_check_congested(struct drbd_conf *mdev)
|
|||||||
else /*nc->on_congestion == OC_DISCONNECT */
|
else /*nc->on_congestion == OC_DISCONNECT */
|
||||||
_drbd_set_state(_NS(mdev, conn, C_DISCONNECTING), 0, NULL);
|
_drbd_set_state(_NS(mdev, conn, C_DISCONNECTING), 0, NULL);
|
||||||
}
|
}
|
||||||
|
put_ldev(mdev);
|
||||||
return congested;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If this returns false, and req->private_bio is still set,
|
/* If this returns false, and req->private_bio is still set,
|
||||||
@ -923,7 +929,7 @@ static int drbd_process_write_request(struct drbd_request *req)
|
|||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
remote = drbd_should_do_remote(mdev->state);
|
remote = drbd_should_do_remote(mdev->state);
|
||||||
if (remote) {
|
if (remote) {
|
||||||
conn_check_congested(mdev);
|
maybe_pull_ahead(mdev);
|
||||||
remote = drbd_should_do_remote(mdev->state);
|
remote = drbd_should_do_remote(mdev->state);
|
||||||
}
|
}
|
||||||
send_oos = drbd_should_send_out_of_sync(mdev->state);
|
send_oos = drbd_should_send_out_of_sync(mdev->state);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user