@@ -42,6 +42,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/dma-buf.h>
#include <linux/fdtable.h>
#include <linux/file.h>
#include <linux/freezer.h>
@@ -2170,7 +2171,7 @@ static int binder_translate_handle(struct flat_binder_object *fp,
return ret;
}
-static int binder_translate_fd(u32 fd, binder_size_t fd_offset,
+static int binder_translate_fd(u32 fd, binder_size_t fd_offset, __u32 flags,
struct binder_transaction *t,
struct binder_thread *thread,
struct binder_transaction *in_reply_to)
@@ -2208,6 +2209,26 @@ static int binder_translate_fd(u32 fd, binder_size_t fd_offset,
goto err_security;
}
+ if (IS_ENABLED(CONFIG_CGROUP_GPU) && (flags & BINDER_FD_FLAG_XFER_CHARGE)) {
+ struct dma_buf *dmabuf;
+
+ if (!is_dma_buf_file(file)) {
+ binder_user_error(
+ "%d:%d got transaction with XFER_CHARGE for non-dmabuf fd, %d\n",
+ proc->pid, thread->pid, fd);
+ ret = -EINVAL;
+ goto err_dmabuf;
+ }
+
+ dmabuf = file->private_data;
+ ret = dma_buf_transfer_charge(dmabuf, target_proc->tsk);
+ if (ret) {
+ pr_warn("%d:%d Unable to transfer DMA-BUF fd charge to %d\n",
+ proc->pid, thread->pid, target_proc->pid);
+ goto err_xfer;
+ }
+ }
+
/*
* Add fixup record for this transaction. The allocation
* of the fd in the target needs to be done from a
@@ -2226,6 +2247,8 @@ static int binder_translate_fd(u32 fd, binder_size_t fd_offset,
return ret;
err_alloc:
+err_xfer:
+err_dmabuf:
err_security:
fput(file);
err_fget:
@@ -2528,7 +2551,7 @@ static int binder_translate_fd_array(struct list_head *pf_head,
ret = copy_from_user(&fd, sender_ufda_base + sender_uoffset, sizeof(fd));
if (!ret)
- ret = binder_translate_fd(fd, offset, t, thread,
+ ret = binder_translate_fd(fd, offset, fda->flags, t, thread,
in_reply_to);
if (ret)
return ret > 0 ? -EINVAL : ret;
@@ -3179,8 +3202,8 @@ static void binder_transaction(struct binder_proc *proc,
struct binder_fd_object *fp = to_binder_fd_object(hdr);
binder_size_t fd_offset = object_offset +
(uintptr_t)&fp->fd - (uintptr_t)fp;
- int ret = binder_translate_fd(fp->fd, fd_offset, t,
- thread, in_reply_to);
+ int ret = binder_translate_fd(fp->fd, fd_offset, fp->flags,
+ t, thread, in_reply_to);
fp->pad_binder = 0;
if (ret < 0 ||
@@ -31,7 +31,6 @@
#include "dma-buf-sysfs-stats.h"
-static inline int is_dma_buf_file(struct file *);
struct dma_buf_list {
struct list_head head;
@@ -400,10 +399,11 @@ static const struct file_operations dma_buf_fops = {
/*
* is_dma_buf_file - Check if struct file* is associated with dma_buf
*/
-static inline int is_dma_buf_file(struct file *file)
+int is_dma_buf_file(struct file *file)
{
return file->f_op == &dma_buf_fops;
}
+EXPORT_SYMBOL_NS_GPL(is_dma_buf_file, DMA_BUF);
static struct file *dma_buf_getfile(struct dma_buf *dmabuf, int flags)
{
@@ -614,7 +614,7 @@ dma_buf_attachment_is_dynamic(struct dma_buf_attachment *attach)
{
return !!attach->importer_ops;
}
-
+int is_dma_buf_file(struct file *file);
struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
struct device *dev);
struct dma_buf_attachment *
@@ -91,14 +91,14 @@ struct flat_binder_object {
/**
* struct binder_fd_object - describes a filedescriptor to be fixed up.
* @hdr: common header structure
- * @pad_flags: padding to remain compatible with old userspace code
+ * @flags: One or more BINDER_FD_FLAG_* flags
* @pad_binder: padding to remain compatible with old userspace code
* @fd: file descriptor
* @cookie: opaque data, used by user-space
*/
struct binder_fd_object {
struct binder_object_header hdr;
- __u32 pad_flags;
+ __u32 flags;
union {
binder_uintptr_t pad_binder;
__u32 fd;
@@ -107,6 +107,17 @@ struct binder_fd_object {
binder_uintptr_t cookie;
};
+enum {
+ /**
+ * @BINDER_FD_FLAG_XFER_CHARGE
+ *
+ * When set, the sender of a binder_fd_object wishes to relinquish ownership of the fd for
+ * memory accounting purposes. If the fd is for a DMA-BUF, the buffer is uncharged from the
+ * sender's cgroup and charged to the receiving process's cgroup instead.
+ */
+ BINDER_FD_FLAG_XFER_CHARGE = 0x2000,
+};
+
/* struct binder_buffer_object - object describing a userspace buffer
* @hdr: common header structure
* @flags: one or more BINDER_BUFFER_* flags
@@ -141,7 +152,7 @@ enum {
/* struct binder_fd_array_object - object describing an array of fds in a buffer
* @hdr: common header structure
- * @pad: padding to ensure correct alignment
+ * @flags: One or more BINDER_FDA_FLAG_* flags
* @num_fds: number of file descriptors in the buffer
* @parent: index in offset array to buffer holding the fd array
* @parent_offset: start offset of fd array in the buffer
@@ -162,12 +173,16 @@ enum {
*/
struct binder_fd_array_object {
struct binder_object_header hdr;
- __u32 pad;
+ __u32 flags;
binder_size_t num_fds;
binder_size_t parent;
binder_size_t parent_offset;
};
+enum {
+ BINDER_FDA_FLAG_XFER_CHARGE = BINDER_FD_FLAG_XFER_CHARGE,
+};
+
/*
* On 64-bit platforms where user code may run in 32-bits the driver must
* translate the buffer (and local binder) addresses appropriately.