summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavankumar Kondeti <quic_pkondeti@quicinc.com>2022-12-08 16:16:37 +0530
committerT.J. Mercier <tjmercier@google.com>2024-01-09 17:43:59 +0000
commit227b55a7a3ccacd83510b176f4d879de1887b2fa (patch)
treec46d846d96363bce36dcc7fe81459441e75831bf
parentc1b1201d39dcb59bf20e45f40459ea25b37392b7 (diff)
downloadcommon-227b55a7a3ccacd83510b176f4d879de1887b2fa.tar.gz
ANDROID: dma-buf: don't re-purpose kobject as work_struct
The commit 5aec776ef8c9 ("BACKPORT: ANDROID: dma-buf: Move sysfs work out of DMA-BUF export path) re-purposed kobject as work_struct temporarily to create the sysfs entries asynchronously. The author knows what he is doing and rightly added a build assert if kobject struct size is smaller than the work_struct size. We are hitting this build assert on a non-GKI platform where CONFIG_ANDROID_KABI_RESERVE is not set. Fix this problem by allocating a new union with dma_buf_sysfs_entry structure and temporary structure as members. We only end up allocating more memory (because of union) only when kobject size is smaller than work_struct which the original patch any way assumed would never be true. Bug: 261818147 Bug: 262666413 Change-Id: Ifb089bf80d8a3a44ece9f05fc0b99ee76cb11645 Signed-off-by: Pavankumar Kondeti <quic_pkondeti@quicinc.com> (cherry picked from commit ce18af9b5d7d0baad2ac3eea4c732d2bf128d690) Signed-off-by: T.J. Mercier <tjmercier@google.com>
-rw-r--r--drivers/dma-buf/dma-buf-sysfs-stats.c44
1 files changed, 24 insertions, 20 deletions
diff --git a/drivers/dma-buf/dma-buf-sysfs-stats.c b/drivers/dma-buf/dma-buf-sysfs-stats.c
index 46520c4d8ec9..4f3ee92dbe1b 100644
--- a/drivers/dma-buf/dma-buf-sysfs-stats.c
+++ b/drivers/dma-buf/dma-buf-sysfs-stats.c
@@ -169,15 +169,21 @@ void dma_buf_uninit_sysfs_statistics(void)
kset_unregister(dma_buf_stats_kset);
}
+struct dma_buf_create_sysfs_entry {
+ struct dma_buf *dmabuf;
+ struct work_struct work;
+};
+
+union dma_buf_create_sysfs_work_entry {
+ struct dma_buf_create_sysfs_entry create_entry;
+ struct dma_buf_sysfs_entry sysfs_entry;
+};
+
static void sysfs_add_workfn(struct work_struct *work)
{
- /* The ABI would have to change for this to be false, but let's be paranoid. */
- _Static_assert(sizeof(struct kobject) >= sizeof(struct work_struct),
- "kobject is smaller than work_struct");
-
- struct dma_buf_sysfs_entry *sysfs_entry =
- container_of((struct kobject *)work, struct dma_buf_sysfs_entry, kobj);
- struct dma_buf *dmabuf = sysfs_entry->dmabuf;
+ struct dma_buf_create_sysfs_entry *create_entry =
+ container_of(work, struct dma_buf_create_sysfs_entry, work);
+ struct dma_buf *dmabuf = create_entry->dmabuf;
/*
* A dmabuf is ref-counted via its file member. If this handler holds the only
@@ -188,6 +194,7 @@ static void sysfs_add_workfn(struct work_struct *work)
* is released, and that can't happen until the end of this function.
*/
if (file_count(dmabuf->file) > 1) {
+ dmabuf->sysfs_entry->dmabuf = dmabuf;
/*
* kobject_init_and_add expects kobject to be zero-filled, but we have populated it
* (the sysfs_add_work union member) to trigger this work function.
@@ -212,29 +219,26 @@ static void sysfs_add_workfn(struct work_struct *work)
int dma_buf_stats_setup(struct dma_buf *dmabuf, struct file *file)
{
- struct dma_buf_sysfs_entry *sysfs_entry;
- struct work_struct *work;
+ struct dma_buf_create_sysfs_entry *create_entry;
+ union dma_buf_create_sysfs_work_entry *work_entry;
if (!dmabuf->exp_name) {
pr_err("exporter name must not be empty if stats needed\n");
return -EINVAL;
}
- sysfs_entry = kmalloc(sizeof(struct dma_buf_sysfs_entry), GFP_KERNEL);
- if (!sysfs_entry)
+ work_entry = kmalloc(sizeof(union dma_buf_create_sysfs_work_entry), GFP_KERNEL);
+ if (!work_entry)
return -ENOMEM;
- sysfs_entry->dmabuf = dmabuf;
- dmabuf->sysfs_entry = sysfs_entry;
+ dmabuf->sysfs_entry = &work_entry->sysfs_entry;
- /*
- * The use of kobj as a work_struct is an ugly hack
- * to avoid an ABI break in this frozen kernel.
- */
- work = (struct work_struct *)&dmabuf->sysfs_entry->kobj;
- INIT_WORK(work, sysfs_add_workfn);
+ create_entry = &work_entry->create_entry;
+ create_entry->dmabuf = dmabuf;
+
+ INIT_WORK(&create_entry->work, sysfs_add_workfn);
get_dma_buf(dmabuf); /* This reference will be dropped in sysfs_add_workfn. */
- schedule_work(work);
+ schedule_work(&create_entry->work);
return 0;
}