This patch adds possibility to add a private data room to the l2cap_chan
structure. This private dataroom will be freed when the l2cap_chan
reference count reach zero. This avoids dealing with separate allocated
data pointer for l2cap_chan "data" attribute.
Signed-off-by: Alexander Aring <redacted>
---
include/net/bluetooth/l2cap.h | 4 ++++
net/bluetooth/l2cap_core.c | 21 +++++++++++++++++++--
2 files changed, 23 insertions(+), 2 deletions(-)
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 8a4d26e..925c78a 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -598,6 +598,9 @@ struct l2cap_chan {
void *data;
const struct l2cap_ops *ops;
struct mutex lock;
+
+ /* must be last */
+ u8 priv[0] __aligned(sizeof(void *));
};
struct l2cap_ops {@@ -925,6 +928,7 @@ int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm);
int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid);
struct l2cap_chan *l2cap_chan_create(void);
+struct l2cap_chan *l2cap_chan_create_priv(size_t priv_size);
void l2cap_chan_close(struct l2cap_chan *chan, int reason);
int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
bdaddr_t *dst, u8 dst_type);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 2ab8814..cce5d21 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -433,11 +433,11 @@ static void l2cap_chan_timeout(struct work_struct *work)
l2cap_chan_put(chan);
}
-struct l2cap_chan *l2cap_chan_create(void)
+static struct l2cap_chan *__l2cap_chan_create(size_t priv_size)
{
struct l2cap_chan *chan;
- chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
+ chan = kzalloc(sizeof(*chan) + priv_size, GFP_ATOMIC);
if (!chan)
return NULL;
@@ -463,8 +463,25 @@ struct l2cap_chan *l2cap_chan_create(void)
return chan;
}
+
+struct l2cap_chan *l2cap_chan_create(void)
+{
+ return __l2cap_chan_create(0);
+}
EXPORT_SYMBOL_GPL(l2cap_chan_create);
+struct l2cap_chan *l2cap_chan_create_priv(size_t priv_size)
+{
+ struct l2cap_chan *chan = __l2cap_chan_create(priv_size);
+
+ /* let's point data pointer to private space */
+ if (chan)
+ chan->data = chan->priv;
+
+ return chan;
+}
+EXPORT_SYMBOL_GPL(l2cap_chan_create_priv);
+
static void l2cap_chan_destroy(struct kref *kref)
{
struct l2cap_chan *chan = container_of(kref, struct l2cap_chan, kref);--
2.9.2