mirror of
https://github.com/torvalds/linux.git
synced 2026-05-25 23:52:08 +02:00
smb: smbdirect: introduce smbdirect_socket_create_{kern,accepting}() and smbdirect_socket_release()
This provides functions which also allocate and free struct smbdirect_socket. This allows callers to use the same flow as with sock_create_kern()/sock_release(). The end goal would be to use sock_create_kern()/sock_release(), but the first step will be to use smbdirect specific functions without any struct socket nor struct sock. Cc: Steve French <smfrench@gmail.com> Cc: Tom Talpey <tom@talpey.com> Cc: Long Li <longli@microsoft.com> Cc: Namjae Jeon <linkinjeon@kernel.org> Cc: linux-cifs@vger.kernel.org Cc: samba-technical@lists.samba.org Signed-off-by: Stefan Metzmacher <metze@samba.org> Acked-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
eb3ed1e904
commit
20cd3cc442
|
|
@ -51,7 +51,6 @@ static int smbdirect_socket_rdma_event_handler(struct rdma_cm_id *id,
|
|||
return -ESTALE;
|
||||
}
|
||||
|
||||
__maybe_unused /* this is temporary while this file is included in others */
|
||||
static int smbdirect_socket_init_new(struct net *net, struct smbdirect_socket *sc)
|
||||
{
|
||||
struct rdma_cm_id *id;
|
||||
|
|
@ -85,6 +84,31 @@ static int smbdirect_socket_init_new(struct net *net, struct smbdirect_socket *s
|
|||
}
|
||||
|
||||
__maybe_unused /* this is temporary while this file is included in others */
|
||||
static int smbdirect_socket_create_kern(struct net *net, struct smbdirect_socket **_sc)
|
||||
{
|
||||
struct smbdirect_socket *sc;
|
||||
int ret;
|
||||
|
||||
ret = -ENOMEM;
|
||||
sc = kzalloc_obj(*sc);
|
||||
if (!sc)
|
||||
goto alloc_failed;
|
||||
|
||||
ret = smbdirect_socket_init_new(net, sc);
|
||||
if (ret)
|
||||
goto init_failed;
|
||||
|
||||
kref_init(&sc->refs.destroy);
|
||||
|
||||
*_sc = sc;
|
||||
return 0;
|
||||
|
||||
init_failed:
|
||||
kfree(sc);
|
||||
alloc_failed:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int smbdirect_socket_init_accepting(struct rdma_cm_id *id, struct smbdirect_socket *sc)
|
||||
{
|
||||
smbdirect_socket_init(sc);
|
||||
|
|
@ -100,6 +124,32 @@ static int smbdirect_socket_init_accepting(struct rdma_cm_id *id, struct smbdire
|
|||
return 0;
|
||||
}
|
||||
|
||||
__maybe_unused /* this is temporary while this file is included in others */
|
||||
static int smbdirect_socket_create_accepting(struct rdma_cm_id *id, struct smbdirect_socket **_sc)
|
||||
{
|
||||
struct smbdirect_socket *sc;
|
||||
int ret;
|
||||
|
||||
ret = -ENOMEM;
|
||||
sc = kzalloc_obj(*sc);
|
||||
if (!sc)
|
||||
goto alloc_failed;
|
||||
|
||||
ret = smbdirect_socket_init_accepting(id, sc);
|
||||
if (ret)
|
||||
goto init_failed;
|
||||
|
||||
kref_init(&sc->refs.destroy);
|
||||
|
||||
*_sc = sc;
|
||||
return 0;
|
||||
|
||||
init_failed:
|
||||
kfree(sc);
|
||||
alloc_failed:
|
||||
return ret;
|
||||
}
|
||||
|
||||
__maybe_unused /* this is temporary while this file is included in others */
|
||||
static int smbdirect_socket_set_initial_parameters(struct smbdirect_socket *sc,
|
||||
const struct smbdirect_socket_parameters *sp)
|
||||
|
|
@ -556,6 +606,49 @@ static void smbdirect_socket_shutdown(struct smbdirect_socket *sc)
|
|||
smbdirect_socket_schedule_cleanup_lvl(sc, SMBDIRECT_LOG_INFO, -ESHUTDOWN);
|
||||
}
|
||||
|
||||
static void smbdirect_socket_release_disconnect(struct kref *kref)
|
||||
{
|
||||
struct smbdirect_socket *sc =
|
||||
container_of(kref, struct smbdirect_socket, refs.disconnect);
|
||||
|
||||
/*
|
||||
* For now do a sync disconnect/destroy
|
||||
*/
|
||||
smbdirect_socket_destroy_sync(sc);
|
||||
}
|
||||
|
||||
static void smbdirect_socket_release_destroy(struct kref *kref)
|
||||
{
|
||||
struct smbdirect_socket *sc =
|
||||
container_of(kref, struct smbdirect_socket, refs.destroy);
|
||||
|
||||
/*
|
||||
* Do a sync disconnect/destroy...
|
||||
* hopefully a no-op, as it should be already
|
||||
* in DESTROYED state, before we free the memory.
|
||||
*/
|
||||
smbdirect_socket_destroy_sync(sc);
|
||||
kfree(sc);
|
||||
}
|
||||
|
||||
__maybe_unused /* this is temporary while this file is included in others */
|
||||
static void smbdirect_socket_release(struct smbdirect_socket *sc)
|
||||
{
|
||||
/*
|
||||
* We expect only 1 disconnect reference
|
||||
* and if it is already 0, it's a use after free!
|
||||
*/
|
||||
WARN_ON_ONCE(kref_read(&sc->refs.disconnect) != 1);
|
||||
WARN_ON(!kref_put(&sc->refs.disconnect, smbdirect_socket_release_disconnect));
|
||||
|
||||
/*
|
||||
* This may not trigger smbdirect_socket_release_destroy(),
|
||||
* if struct smbdirect_socket is embedded in another structure
|
||||
* indicated by REFCOUNT_MAX.
|
||||
*/
|
||||
kref_put(&sc->refs.destroy, smbdirect_socket_release_destroy);
|
||||
}
|
||||
|
||||
__maybe_unused /* this is temporary while this file is included in others */
|
||||
static int smbdirect_socket_wait_for_credits(struct smbdirect_socket *sc,
|
||||
enum smbdirect_socket_status expected_status,
|
||||
|
|
|
|||
|
|
@ -108,6 +108,36 @@ struct smbdirect_socket {
|
|||
|
||||
struct work_struct disconnect_work;
|
||||
|
||||
/*
|
||||
* The reference counts.
|
||||
*/
|
||||
struct {
|
||||
/*
|
||||
* This holds the references by the
|
||||
* frontend, typically the smb layer.
|
||||
*
|
||||
* It is typically 1 and a disconnect
|
||||
* will happen if it reaches 0.
|
||||
*/
|
||||
struct kref disconnect;
|
||||
|
||||
/*
|
||||
* This holds the reference by the
|
||||
* backend, the code that manages
|
||||
* the lifetime of the whole
|
||||
* struct smbdirect_socket,
|
||||
* if this reaches 0 it can will
|
||||
* be freed.
|
||||
*
|
||||
* Can be REFCOUNT_MAX is part
|
||||
* of another structure.
|
||||
*
|
||||
* This is equal or higher than
|
||||
* the disconnect refcount.
|
||||
*/
|
||||
struct kref destroy;
|
||||
} refs;
|
||||
|
||||
/* RDMA related */
|
||||
struct {
|
||||
struct rdma_cm_id *cm_id;
|
||||
|
|
@ -513,6 +543,9 @@ static __always_inline void smbdirect_socket_init(struct smbdirect_socket *sc)
|
|||
INIT_WORK(&sc->disconnect_work, __smbdirect_socket_disabled_work);
|
||||
disable_work_sync(&sc->disconnect_work);
|
||||
|
||||
kref_init(&sc->refs.disconnect);
|
||||
sc->refs.destroy = (struct kref) KREF_INIT(REFCOUNT_MAX);
|
||||
|
||||
sc->rdma.expected_event = RDMA_CM_EVENT_INTERNAL;
|
||||
|
||||
sc->ib.poll_ctx = IB_POLL_UNBOUND_WORKQUEUE;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user