2021-07-13 09:31:08

by Hanjun Guo

[permalink] [raw]
Subject: [Backport for 5.10.y PATCH 0/7] Patches for 5.10.y

Hi Greg, Sasha,

Patches below are some collections of bugfixes, those fixes are
found when we are using the stable 5.10 kernel, please consider
to apply them, I also Cced the author and maintainer for each
patch to see if any objections.


Patch 2/7 will fix the failure of LTP test case 'move_pages 12',
and patch 3/7 is not a bugfix but a preparation for later bugfixes,
other patches are obvious bugfixes.


Gulam Mohamed (1):
scsi: iscsi: Fix race condition between login and sync thread

Jens Axboe (1):
io_uring: convert io_buffer_idr to XArray

Matthew Wilcox (Oracle) (1):
io_uring: Convert personality_idr to XArray

Mauricio Faria de Oliveira (1):
loop: fix I/O error on fsync() in detached loop devices

Mike Christie (1):
scsi: iscsi: Fix iSCSI cls conn state

Oscar Salvador (1):
mm,hwpoison: return -EBUSY when migration fails

Yejune Deng (1):
io_uring: simplify io_remove_personalities()

drivers/block/loop.c | 3 +
drivers/scsi/libiscsi.c | 26 +-------
drivers/scsi/scsi_transport_iscsi.c | 28 ++++++++-
fs/io_uring.c | 116 +++++++++++++++---------------------
include/scsi/scsi_transport_iscsi.h | 1 +
mm/memory-failure.c | 6 +-
6 files changed, 85 insertions(+), 95 deletions(-)

--
1.7.12.4


2021-07-13 09:31:41

by Hanjun Guo

[permalink] [raw]
Subject: [Backport for 5.10.y PATCH 5/7] io_uring: convert io_buffer_idr to XArray

From: Jens Axboe <[email protected]>

commit 9e15c3a0ced5a61f320b989072c24983cb1620c1 upstream.

Like we did for the personality idr, convert the IO buffer idr to use
XArray. This avoids a use-after-free on removal of entries, since idr
doesn't like doing so from inside an iterator, and it nicely reduces
the amount of code we need to support this feature.

Fixes: 5a2e745d4d43 ("io_uring: buffer registration infrastructure")
Cc: [email protected]
Cc: Matthew Wilcox <[email protected]>
Cc: yangerkun <[email protected]>
Reported-by: Hulk Robot <[email protected]>
Signed-off-by: Jens Axboe <[email protected]>
Signed-off-by: Hanjun Guo <[email protected]>
---
fs/io_uring.c | 43 +++++++++++++++----------------------------
1 file changed, 15 insertions(+), 28 deletions(-)

diff --git a/fs/io_uring.c b/fs/io_uring.c
index cd93bf5..fb63cc8 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -344,7 +344,7 @@ struct io_ring_ctx {
struct socket *ring_sock;
#endif

- struct idr io_buffer_idr;
+ struct xarray io_buffers;

struct xarray personalities;
u32 pers_next;
@@ -1212,7 +1212,7 @@ static struct io_ring_ctx *io_ring_ctx_alloc(struct io_uring_params *p)
INIT_LIST_HEAD(&ctx->cq_overflow_list);
init_completion(&ctx->ref_comp);
init_completion(&ctx->sq_thread_comp);
- idr_init(&ctx->io_buffer_idr);
+ xa_init_flags(&ctx->io_buffers, XA_FLAGS_ALLOC1);
xa_init_flags(&ctx->personalities, XA_FLAGS_ALLOC1);
mutex_init(&ctx->uring_lock);
init_waitqueue_head(&ctx->wait);
@@ -2990,7 +2990,7 @@ static struct io_buffer *io_buffer_select(struct io_kiocb *req, size_t *len,

lockdep_assert_held(&req->ctx->uring_lock);

- head = idr_find(&req->ctx->io_buffer_idr, bgid);
+ head = xa_load(&req->ctx->io_buffers, bgid);
if (head) {
if (!list_empty(&head->list)) {
kbuf = list_last_entry(&head->list, struct io_buffer,
@@ -2998,7 +2998,7 @@ static struct io_buffer *io_buffer_select(struct io_kiocb *req, size_t *len,
list_del(&kbuf->list);
} else {
kbuf = head;
- idr_remove(&req->ctx->io_buffer_idr, bgid);
+ xa_erase(&req->ctx->io_buffers, bgid);
}
if (*len > kbuf->len)
*len = kbuf->len;
@@ -3960,7 +3960,7 @@ static int __io_remove_buffers(struct io_ring_ctx *ctx, struct io_buffer *buf,
}
i++;
kfree(buf);
- idr_remove(&ctx->io_buffer_idr, bgid);
+ xa_erase(&ctx->io_buffers, bgid);

return i;
}
@@ -3978,7 +3978,7 @@ static int io_remove_buffers(struct io_kiocb *req, bool force_nonblock,
lockdep_assert_held(&ctx->uring_lock);

ret = -ENOENT;
- head = idr_find(&ctx->io_buffer_idr, p->bgid);
+ head = xa_load(&ctx->io_buffers, p->bgid);
if (head)
ret = __io_remove_buffers(ctx, head, p->bgid, p->nbufs);
if (ret < 0)
@@ -4069,21 +4069,14 @@ static int io_provide_buffers(struct io_kiocb *req, bool force_nonblock,

lockdep_assert_held(&ctx->uring_lock);

- list = head = idr_find(&ctx->io_buffer_idr, p->bgid);
+ list = head = xa_load(&ctx->io_buffers, p->bgid);

ret = io_add_buffers(p, &head);
- if (ret < 0)
- goto out;
-
- if (!list) {
- ret = idr_alloc(&ctx->io_buffer_idr, head, p->bgid, p->bgid + 1,
- GFP_KERNEL);
- if (ret < 0) {
+ if (ret >= 0 && !list) {
+ ret = xa_insert(&ctx->io_buffers, p->bgid, head, GFP_KERNEL);
+ if (ret < 0)
__io_remove_buffers(ctx, head, p->bgid, -1U);
- goto out;
- }
}
-out:
if (ret < 0)
req_set_fail_links(req);

@@ -8411,19 +8404,13 @@ static int io_eventfd_unregister(struct io_ring_ctx *ctx)
return -ENXIO;
}

-static int __io_destroy_buffers(int id, void *p, void *data)
-{
- struct io_ring_ctx *ctx = data;
- struct io_buffer *buf = p;
-
- __io_remove_buffers(ctx, buf, id, -1U);
- return 0;
-}
-
static void io_destroy_buffers(struct io_ring_ctx *ctx)
{
- idr_for_each(&ctx->io_buffer_idr, __io_destroy_buffers, ctx);
- idr_destroy(&ctx->io_buffer_idr);
+ struct io_buffer *buf;
+ unsigned long index;
+
+ xa_for_each(&ctx->io_buffers, index, buf)
+ __io_remove_buffers(ctx, buf, index, -1U);
}

static void io_ring_ctx_free(struct io_ring_ctx *ctx)
--
1.7.12.4

2021-07-13 09:32:07

by Hanjun Guo

[permalink] [raw]
Subject: [Backport for 5.10.y PATCH 3/7] io_uring: simplify io_remove_personalities()

From: Yejune Deng <[email protected]>

commit 0bead8cd39b9c9c7c4e902018ccf129107ac50ef upstream.

The function io_remove_personalities() is very similar to
io_unregister_personality(),so implement io_remove_personalities()
calling io_unregister_personality().

Signed-off-by: Yejune Deng <[email protected]>
Reviewed-by: Pavel Begunkov <[email protected]>
Signed-off-by: Jens Axboe <[email protected]>
Signed-off-by: Hanjun Guo <[email protected]>
---
fs/io_uring.c | 28 +++++++++++-----------------
1 file changed, 11 insertions(+), 17 deletions(-)

diff --git a/fs/io_uring.c b/fs/io_uring.c
index 0138aa7..0cbf2a0 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -8505,9 +8505,8 @@ static int io_uring_fasync(int fd, struct file *file, int on)
return fasync_helper(fd, file, on, &ctx->cq_fasync);
}

-static int io_remove_personalities(int id, void *p, void *data)
+static int io_unregister_personality(struct io_ring_ctx *ctx, unsigned id)
{
- struct io_ring_ctx *ctx = data;
struct io_identity *iod;

iod = idr_remove(&ctx->personality_idr, id);
@@ -8515,7 +8514,17 @@ static int io_remove_personalities(int id, void *p, void *data)
put_cred(iod->creds);
if (refcount_dec_and_test(&iod->count))
kfree(iod);
+ return 0;
}
+
+ return -EINVAL;
+}
+
+static int io_remove_personalities(int id, void *p, void *data)
+{
+ struct io_ring_ctx *ctx = data;
+
+ io_unregister_personality(ctx, id);
return 0;
}

@@ -9606,21 +9615,6 @@ static int io_register_personality(struct io_ring_ctx *ctx)
return ret;
}

-static int io_unregister_personality(struct io_ring_ctx *ctx, unsigned id)
-{
- struct io_identity *iod;
-
- iod = idr_remove(&ctx->personality_idr, id);
- if (iod) {
- put_cred(iod->creds);
- if (refcount_dec_and_test(&iod->count))
- kfree(iod);
- return 0;
- }
-
- return -EINVAL;
-}
-
static int io_register_restrictions(struct io_ring_ctx *ctx, void __user *arg,
unsigned int nr_args)
{
--
1.7.12.4

2021-07-13 09:32:40

by Hanjun Guo

[permalink] [raw]
Subject: [Backport for 5.10.y PATCH 6/7] scsi: iscsi: Fix race condition between login and sync thread

From: Gulam Mohamed <[email protected]>

commit 9e67600ed6b8565da4b85698ec659b5879a6c1c6 upstream.

A kernel panic was observed due to a timing issue between the sync thread
and the initiator processing a login response from the target. The session
reopen can be invoked both from the session sync thread when iscsid
restarts and from iscsid through the error handler. Before the initiator
receives the response to a login, another reopen request can be sent from
the error handler/sync session. When the initial login response is
subsequently processed, the connection has been closed and the socket has
been released.

To fix this a new connection state, ISCSI_CONN_BOUND, is added:

- Set the connection state value to ISCSI_CONN_DOWN upon
iscsi_if_ep_disconnect() and iscsi_if_stop_conn()

- Set the connection state to the newly created value ISCSI_CONN_BOUND
after bind connection (transport->bind_conn())

- In iscsi_set_param(), return -ENOTCONN if the connection state is not
either ISCSI_CONN_BOUND or ISCSI_CONN_UP

Link: https://lore.kernel.org/r/[email protected]
Reviewed-by: Mike Christie <[email protected]>
Signed-off-by: Gulam Mohamed <[email protected]>
Signed-off-by: Martin K. Petersen <[email protected]>
Signed-off-by: Hanjun Guo <[email protected]>
---
drivers/scsi/scsi_transport_iscsi.c | 14 +++++++++++++-
include/scsi/scsi_transport_iscsi.h | 1 +
2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index c520239..cb7b74a0 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -2480,6 +2480,7 @@ static void iscsi_if_stop_conn(struct iscsi_cls_conn *conn, int flag)
*/
mutex_lock(&conn_mutex);
conn->transport->stop_conn(conn, flag);
+ conn->state = ISCSI_CONN_DOWN;
mutex_unlock(&conn_mutex);

}
@@ -2906,6 +2907,13 @@ int iscsi_session_event(struct iscsi_cls_session *session,
default:
err = transport->set_param(conn, ev->u.set_param.param,
data, ev->u.set_param.len);
+ if ((conn->state == ISCSI_CONN_BOUND) ||
+ (conn->state == ISCSI_CONN_UP)) {
+ err = transport->set_param(conn, ev->u.set_param.param,
+ data, ev->u.set_param.len);
+ } else {
+ return -ENOTCONN;
+ }
}

return err;
@@ -2965,6 +2973,7 @@ static int iscsi_if_ep_disconnect(struct iscsi_transport *transport,
mutex_lock(&conn->ep_mutex);
conn->ep = NULL;
mutex_unlock(&conn->ep_mutex);
+ conn->state = ISCSI_CONN_DOWN;
}

transport->ep_disconnect(ep);
@@ -3732,6 +3741,8 @@ static int iscsi_logout_flashnode_sid(struct iscsi_transport *transport,
ev->r.retcode = transport->bind_conn(session, conn,
ev->u.b_conn.transport_eph,
ev->u.b_conn.is_leading);
+ if (!ev->r.retcode)
+ conn->state = ISCSI_CONN_BOUND;
mutex_unlock(&conn_mutex);

if (ev->r.retcode || !transport->ep_connect)
@@ -3971,7 +3982,8 @@ static ISCSI_CLASS_ATTR(conn, field, S_IRUGO, show_conn_param_##param, \
static const char *const connection_state_names[] = {
[ISCSI_CONN_UP] = "up",
[ISCSI_CONN_DOWN] = "down",
- [ISCSI_CONN_FAILED] = "failed"
+ [ISCSI_CONN_FAILED] = "failed",
+ [ISCSI_CONN_BOUND] = "bound"
};

static ssize_t show_conn_state(struct device *dev,
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
index 8a26a2f..fc5a398 100644
--- a/include/scsi/scsi_transport_iscsi.h
+++ b/include/scsi/scsi_transport_iscsi.h
@@ -193,6 +193,7 @@ enum iscsi_connection_state {
ISCSI_CONN_UP = 0,
ISCSI_CONN_DOWN,
ISCSI_CONN_FAILED,
+ ISCSI_CONN_BOUND,
};

struct iscsi_cls_conn {
--
1.7.12.4

2021-07-15 16:05:33

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [Backport for 5.10.y PATCH 0/7] Patches for 5.10.y

On Tue, Jul 13, 2021 at 05:18:30PM +0800, Hanjun Guo wrote:
> Hi Greg, Sasha,
>
> Patches below are some collections of bugfixes, those fixes are
> found when we are using the stable 5.10 kernel, please consider
> to apply them, I also Cced the author and maintainer for each
> patch to see if any objections.
>

All look good, thanks for these, now queued up.

greg k-h