* [PATCH v2 0/1] Zerocopy for USB Gadget FunctionFS
@ 2022-02-02 17:20 Ingo Rohloff
2022-02-02 17:20 ` [PATCH v2 1/1] usb: gadget: f_fs: Support zerocopy transfers via mmap Ingo Rohloff
0 siblings, 1 reply; 6+ messages in thread
From: Ingo Rohloff @ 2022-02-02 17:20 UTC (permalink / raw)
To: gregkh, balbi; +Cc: linux-usb, Ingo Rohloff
The
commit f7d34b445abc00e979b7 ("USB: Add support for usbfs zerocopy.")
added support for zerocopy operations for an USB Host via devio.c
The idea is to mmap buffers into user space, which are then filled
with data (either by the kernel for reads or by the user for writes).
Using these mmapped buffers avoids copying data between kernel space
and user space.
The patch proposed here, tries to do the same for a USB Gadget and a
user space application using USB Gaget FunctionFS.
Note: As long as you do not use mmap and/or libaio, FunctionFS should
behave exactly as before.
V2:
The mmapped buffers are now associated with a "struct file *".
This is achieved by adding another in-between
"struct ffs_ep_listener", which is allocated per "struct file *".
I believe I botched that up in the previous V1 proposal;
It seems using a list of mmapped segments associated to a
"struct file *" is the right approach?
To limit the amount of memory user space processes might mmap, per
default this is limited to 16 MiB per FunctionFS mount point. This
limit can be modified at the time FunctionFS is mounted, by using the
mount option "mmap_memory_mb=<value>", specifying the allowed mmap
space in MiB.
Example:
mount -t functionfs -ommap_memory_mb=1 usb0 /usbfunc
A value of 0 means there is NO LIMIT on the amount of memory a user
space application might mmap in total.
If you want to try out, I updated the demonstration code accordingly:
https://github.com/trace32/test_usb_ffs
so long
Ingo
Ingo Rohloff (1):
usb: gadget: f_fs: Support zerocopy transfers via mmap.
drivers/usb/gadget/function/f_fs.c | 268 ++++++++++++++++++++++++++++-
drivers/usb/gadget/function/u_fs.h | 4 +
2 files changed, 266 insertions(+), 6 deletions(-)
--
2.17.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2 1/1] usb: gadget: f_fs: Support zerocopy transfers via mmap.
2022-02-02 17:20 [PATCH v2 0/1] Zerocopy for USB Gadget FunctionFS Ingo Rohloff
@ 2022-02-02 17:20 ` Ingo Rohloff
2022-02-08 10:44 ` Greg KH
0 siblings, 1 reply; 6+ messages in thread
From: Ingo Rohloff @ 2022-02-02 17:20 UTC (permalink / raw)
To: gregkh, balbi; +Cc: linux-usb, Ingo Rohloff
This patch implements the same functionality for FunctionFS as
commit f7d34b445abc00e979b7 ("USB: Add support for usbfs zerocopy.")
did for USB host devio.c
For FunctionFS, each "struct file *" for an endpoint (except EP0), keeps
a list of mmapped buffers. User space might use these buffers to avoid
copying of data by the kernel, by employing Linux native AsyncIO via
libaio.
Standard read() and write() operations will NOT be zerocopy.
Especially for reads, the expected USB transfer length is unclear;
whereas an AIO request clearly specifies the maximum transfer length.
Signed-off-by: Ingo Rohloff <ingo.rohloff@lauterbach.com>
---
drivers/usb/gadget/function/f_fs.c | 269 ++++++++++++++++++++++++++++-
drivers/usb/gadget/function/u_fs.h | 4 +
2 files changed, 267 insertions(+), 6 deletions(-)
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index 7461d27e9604..a2e46704426f 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -201,6 +201,23 @@ struct ffs_epfile {
unsigned char _pad;
};
+struct ffs_ep_listener {
+ struct ffs_epfile *epfile;
+ struct list_head ffsm_list;
+ spinlock_t ffsm_lock;
+};
+
+struct ffs_memory {
+ struct list_head memlist;
+ struct ffs_ep_listener *listener;
+ char *kmem;
+ unsigned long vm_start;
+ u32 size;
+
+ int vma_use_count;
+ int aio_use_count;
+};
+
struct ffs_buffer {
size_t length;
char *data;
@@ -227,6 +244,7 @@ struct ffs_io_data {
bool use_sg;
struct ffs_data *ffs;
+ struct ffs_memory *ffsm;
};
struct ffs_desc_helper {
@@ -702,6 +720,200 @@ static const struct file_operations ffs_ep0_operations = {
.poll = ffs_ep0_poll,
};
+/* Handling of mmapped transfers *******************************/
+
+/* Check whether it's okay to allocate more memory for mmap */
+static int ffsm_increase_mmap_mem_usage(struct ffs_data *ffs, u64 amount)
+{
+ u64 lim;
+
+ lim = READ_ONCE(ffs->mmap_memory_mb);
+ lim <<= 20;
+
+ atomic64_add(amount, &ffs->mmap_mem_usage);
+
+ if (lim > 0 && atomic64_read(&ffs->mmap_mem_usage) > lim) {
+ atomic64_sub(amount, &ffs->mmap_mem_usage);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+/* Memory for mmap is being deallocated */
+static void ffsm_decrease_mmap_mem_usage(struct ffs_data *ffs, u64 amount)
+{
+ atomic64_sub(amount, &ffs->mmap_mem_usage);
+}
+
+static char *ffsm_is_mmapped(
+ struct ffs_ep_listener *listener,
+ struct ffs_io_data *io_data,
+ ssize_t data_len
+)
+{
+ struct iov_iter *i = &io_data->data;
+ struct ffs_memory *ffsm;
+ char *data;
+ unsigned long user_data_start;
+
+ // direct transfer into user memory only allowed for
+ // * AIO (Async IO via libaio)
+ // * IOVEC (must be an IO vector)
+ // * Single AIO transfers (NOT for PREADV, PWRITEV)
+ // * Transfer size must not have been modified
+ if (!io_data->aio)
+ return NULL;
+ if (!iter_is_iovec(i))
+ return NULL;
+ if (i->nr_segs != 1)
+ return NULL;
+ if (i->iov->iov_len != data_len)
+ return NULL;
+
+ // Now check if this is an mmapped segment
+ data = NULL;
+ user_data_start = (unsigned long)i->iov->iov_base;
+
+ spin_lock_irq(&listener->ffsm_lock);
+ list_for_each_entry(ffsm, &listener->ffsm_list, memlist) {
+ if (
+ user_data_start >= ffsm->vm_start &&
+ user_data_start < ffsm->vm_start + ffsm->size
+ ) {
+ if (
+ data_len <= ffsm->vm_start + ffsm->size -
+ user_data_start
+ ) {
+ ffsm->aio_use_count++;
+ data = ffsm->kmem;
+ data += user_data_start - ffsm->vm_start;
+ io_data->ffsm = ffsm;
+ io_data->use_sg = false;
+ }
+ break;
+ }
+ }
+ spin_unlock_irq(&listener->ffsm_lock);
+ return data;
+}
+
+static void ffsm_dec_use_count(struct ffs_memory *ffsm, int *count)
+{
+ struct ffs_ep_listener *listener = ffsm->listener;
+ size_t size;
+ unsigned long flags;
+ struct ffs_data *ffs;
+
+ spin_lock_irqsave(&listener->ffsm_lock, flags);
+ *count = *count - 1;
+ if (ffsm->aio_use_count != 0 || ffsm->vma_use_count != 0) {
+ spin_unlock_irqrestore(&listener->ffsm_lock, flags);
+ return;
+ }
+
+ list_del(&ffsm->memlist);
+ spin_unlock_irqrestore(&listener->ffsm_lock, flags);
+
+ ffs = listener->epfile->ffs;
+ size = ffsm->size;
+ kfree(ffsm->kmem);
+ kfree(ffsm);
+ ffsm_decrease_mmap_mem_usage(ffs, size + sizeof(struct ffs_memory));
+}
+
+static void ffsm_vm_open(struct vm_area_struct *vma)
+{
+ struct ffs_memory *ffsm = vma->vm_private_data;
+ struct ffs_ep_listener *listener = ffsm->listener;
+ unsigned long flags;
+
+ spin_lock_irqsave(&listener->ffsm_lock, flags);
+ ++ffsm->vma_use_count;
+ spin_unlock_irqrestore(&listener->ffsm_lock, flags);
+}
+
+static void ffsm_vm_close(struct vm_area_struct *vma)
+{
+ struct ffs_memory *ffsm = vma->vm_private_data;
+
+ ffsm_dec_use_count(ffsm, &ffsm->vma_use_count);
+}
+
+static const struct vm_operations_struct ffsm_vm_ops = {
+ .open = ffsm_vm_open,
+ .close = ffsm_vm_close
+};
+
+static int ffs_epfile_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct ffs_ep_listener *listener = file->private_data;
+ struct ffs_memory *ffsm = NULL;
+ size_t size = vma->vm_end - vma->vm_start;
+ char *kmem;
+ int rc, ret;
+
+ if (!IS_ALIGNED(size, PAGE_SIZE))
+ return -EFAULT;
+
+ rc = ffsm_increase_mmap_mem_usage(
+ listener->epfile->ffs,
+ size + sizeof(struct ffs_memory)
+ );
+ if (rc)
+ return -ENOMEM;
+
+ ret = 0;
+ ffsm = kzalloc(sizeof(struct ffs_memory), GFP_KERNEL);
+ if (!ffsm) {
+ ret = -ENOMEM;
+ goto error_decrease_mem;
+ }
+
+ kmem = kzalloc(size, GFP_USER | __GFP_NOWARN);
+ if (!kmem) {
+ kfree(ffsm);
+ ret = -ENOMEM;
+ goto error_decrease_mem;
+ }
+
+ rc = remap_pfn_range(
+ vma,
+ vma->vm_start,
+ PHYS_PFN(virt_to_phys(kmem)),
+ size,
+ vma->vm_page_prot
+ );
+ if (rc < 0) {
+ kfree(kmem);
+ kfree(ffsm);
+ ret = -EAGAIN;
+ goto error_decrease_mem;
+ }
+
+
+ INIT_LIST_HEAD(&ffsm->memlist);
+ ffsm->listener = listener;
+ ffsm->kmem = kmem;
+ ffsm->vm_start = vma->vm_start;
+ ffsm->size = size;
+ ffsm->vma_use_count = 1;
+
+ vma->vm_ops = &ffsm_vm_ops;
+ vma->vm_private_data = ffsm;
+
+ spin_lock_irq(&listener->ffsm_lock);
+ list_add_tail(&ffsm->memlist, &listener->ffsm_list);
+ spin_unlock_irq(&listener->ffsm_lock);
+ return 0;
+
+error_decrease_mem:
+ ffsm_decrease_mmap_mem_usage(
+ listener->epfile->ffs,
+ size + sizeof(struct ffs_memory)
+ );
+ return ret;
+}
/* "Normal" endpoints operations ********************************************/
@@ -824,8 +1036,12 @@ static void ffs_user_copy_worker(struct work_struct *work)
int ret = io_data->req->status ? io_data->req->status :
io_data->req->actual;
bool kiocb_has_eventfd = io_data->kiocb->ki_flags & IOCB_EVENTFD;
+ struct ffs_memory *ffsm = io_data->ffsm;
- if (io_data->read && ret > 0) {
+ if (ffsm) {
+ ffsm_dec_use_count(ffsm, &ffsm->aio_use_count);
+ io_data->buf = NULL;
+ } else if (io_data->read && ret > 0) {
kthread_use_mm(io_data->mm);
ret = ffs_copy_to_iter(io_data->buf, ret, &io_data->data);
kthread_unuse_mm(io_data->mm);
@@ -940,7 +1156,8 @@ static ssize_t __ffs_epfile_read_data(struct ffs_epfile *epfile,
static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
{
- struct ffs_epfile *epfile = file->private_data;
+ struct ffs_ep_listener *listener = file->private_data;
+ struct ffs_epfile *epfile = listener->epfile;
struct usb_request *req;
struct ffs_ep *ep;
char *data = NULL;
@@ -1014,6 +1231,10 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
io_data->use_sg = gadget->sg_supported && data_len > PAGE_SIZE;
spin_unlock_irq(&epfile->ffs->eps_lock);
+ data = ffsm_is_mmapped(listener, io_data, data_len);
+ if (data)
+ goto start_request;
+
data = ffs_alloc_buffer(io_data, data_len);
if (!data) {
ret = -ENOMEM;
@@ -1026,6 +1247,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
}
}
+start_request:
spin_lock_irq(&epfile->ffs->eps_lock);
if (epfile->ep != ep) {
@@ -1136,14 +1358,27 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
error_mutex:
mutex_unlock(&epfile->mutex);
error:
- if (ret != -EIOCBQUEUED) /* don't free if there is iocb queued */
+ if (ret != -EIOCBQUEUED) {
+ struct ffs_memory *ffsm = io_data->ffsm;
+
+ /* Transfer is not queued. So free transfer buffer. */
+ if (ffsm) {
+ /*
+ * Transfer would have been done via mmapped memory.
+ * Decrease the use count, since we DID NOT queue.
+ */
+ ffsm_dec_use_count(ffsm, &ffsm->aio_use_count);
+ io_data->buf = NULL;
+ }
ffs_free_buffer(io_data);
+ }
return ret;
}
static int
ffs_epfile_open(struct inode *inode, struct file *file)
{
+ struct ffs_ep_listener *listener;
struct ffs_epfile *epfile = inode->i_private;
ENTER();
@@ -1151,7 +1386,14 @@ ffs_epfile_open(struct inode *inode, struct file *file)
if (WARN_ON(epfile->ffs->state != FFS_ACTIVE))
return -ENODEV;
- file->private_data = epfile;
+ listener = kmalloc(sizeof(*listener), GFP_KERNEL);
+ if (!listener)
+ return -ENOMEM;
+ listener->epfile = epfile;
+ INIT_LIST_HEAD(&listener->ffsm_list);
+ spin_lock_init(&listener->ffsm_lock);
+
+ file->private_data = listener;
ffs_data_opened(epfile->ffs);
return stream_open(inode, file);
@@ -1160,7 +1402,8 @@ ffs_epfile_open(struct inode *inode, struct file *file)
static int ffs_aio_cancel(struct kiocb *kiocb)
{
struct ffs_io_data *io_data = kiocb->private;
- struct ffs_epfile *epfile = kiocb->ki_filp->private_data;
+ struct ffs_ep_listener *listener = kiocb->ki_filp->private_data;
+ struct ffs_epfile *epfile = listener->epfile;
unsigned long flags;
int value;
@@ -1268,10 +1511,12 @@ static int
ffs_epfile_release(struct inode *inode, struct file *file)
{
struct ffs_epfile *epfile = inode->i_private;
+ struct ffs_ep_listener *listener = file->private_data;
ENTER();
__ffs_epfile_read_buffer_free(epfile);
+ kfree(listener);
ffs_data_closed(epfile->ffs);
return 0;
@@ -1280,7 +1525,8 @@ ffs_epfile_release(struct inode *inode, struct file *file)
static long ffs_epfile_ioctl(struct file *file, unsigned code,
unsigned long value)
{
- struct ffs_epfile *epfile = file->private_data;
+ struct ffs_ep_listener *listener = file->private_data;
+ struct ffs_epfile *epfile = listener->epfile;
struct ffs_ep *ep;
int ret;
@@ -1366,6 +1612,7 @@ static const struct file_operations ffs_epfile_operations = {
.release = ffs_epfile_release,
.unlocked_ioctl = ffs_epfile_ioctl,
.compat_ioctl = compat_ptr_ioctl,
+ .mmap = ffs_epfile_mmap,
};
@@ -1444,6 +1691,7 @@ struct ffs_sb_fill_data {
umode_t root_mode;
const char *dev_name;
bool no_disconnect;
+ u32 mmap_memory_mb;
struct ffs_data *ffs_data;
};
@@ -1488,6 +1736,7 @@ enum {
Opt_mode,
Opt_uid,
Opt_gid,
+ Opt_mmap_memory_mb,
};
static const struct fs_parameter_spec ffs_fs_fs_parameters[] = {
@@ -1497,6 +1746,7 @@ static const struct fs_parameter_spec ffs_fs_fs_parameters[] = {
fsparam_u32 ("mode", Opt_mode),
fsparam_u32 ("uid", Opt_uid),
fsparam_u32 ("gid", Opt_gid),
+ fsparam_u32 ("mmap_memory_mb", Opt_mmap_memory_mb),
{}
};
@@ -1537,6 +1787,9 @@ static int ffs_fs_parse_param(struct fs_context *fc, struct fs_parameter *param)
if (!gid_valid(data->perms.gid))
goto unmapped_value;
break;
+ case Opt_mmap_memory_mb:
+ data->mmap_memory_mb = result.uint_32;
+ break;
default:
return -ENOPARAM;
@@ -1567,6 +1820,7 @@ static int ffs_fs_get_tree(struct fs_context *fc)
return -ENOMEM;
ffs->file_perms = ctx->perms;
ffs->no_disconnect = ctx->no_disconnect;
+ ffs->mmap_memory_mb = ctx->mmap_memory_mb;
ffs->dev_name = kstrdup(fc->source, GFP_KERNEL);
if (!ffs->dev_name) {
@@ -1616,6 +1870,8 @@ static int ffs_fs_init_fs_context(struct fs_context *fc)
ctx->perms.gid = GLOBAL_ROOT_GID;
ctx->root_mode = S_IFDIR | 0500;
ctx->no_disconnect = false;
+ /* Per default allow 16MiB of mmap buffers per FunctionFS mount */
+ ctx->mmap_memory_mb = 16;
fc->fs_private = ctx;
fc->ops = &ffs_fs_context_ops;
@@ -1752,6 +2008,7 @@ static struct ffs_data *ffs_data_new(const char *dev_name)
refcount_set(&ffs->ref, 1);
atomic_set(&ffs->opened, 0);
+ atomic64_set(&ffs->mmap_mem_usage, 0);
ffs->state = FFS_READ_DESCRIPTORS;
mutex_init(&ffs->mutex);
spin_lock_init(&ffs->eps_lock);
diff --git a/drivers/usb/gadget/function/u_fs.h b/drivers/usb/gadget/function/u_fs.h
index f102ec23f3af..d3489cfab98c 100644
--- a/drivers/usb/gadget/function/u_fs.h
+++ b/drivers/usb/gadget/function/u_fs.h
@@ -278,6 +278,10 @@ struct ffs_data {
struct eventfd_ctx *ffs_eventfd;
struct workqueue_struct *io_completion_wq;
bool no_disconnect;
+ /* Limit on the total amount of memory we can allocate via mmap */
+ u32 mmap_memory_mb;
+ /* Total memory currently allocated for mmap */
+ atomic64_t mmap_mem_usage;
struct work_struct reset_work;
/*
--
2.17.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v2 1/1] usb: gadget: f_fs: Support zerocopy transfers via mmap.
2022-02-02 17:20 ` [PATCH v2 1/1] usb: gadget: f_fs: Support zerocopy transfers via mmap Ingo Rohloff
@ 2022-02-08 10:44 ` Greg KH
2022-02-08 11:48 ` Ingo Rohloff
0 siblings, 1 reply; 6+ messages in thread
From: Greg KH @ 2022-02-08 10:44 UTC (permalink / raw)
To: Ingo Rohloff; +Cc: balbi, linux-usb
On Wed, Feb 02, 2022 at 06:20:56PM +0100, Ingo Rohloff wrote:
> This patch implements the same functionality for FunctionFS as
> commit f7d34b445abc00e979b7 ("USB: Add support for usbfs zerocopy.")
> did for USB host devio.c
>
> For FunctionFS, each "struct file *" for an endpoint (except EP0), keeps
> a list of mmapped buffers. User space might use these buffers to avoid
> copying of data by the kernel, by employing Linux native AsyncIO via
> libaio.
>
> Standard read() and write() operations will NOT be zerocopy.
> Especially for reads, the expected USB transfer length is unclear;
> whereas an AIO request clearly specifies the maximum transfer length.
>
> Signed-off-by: Ingo Rohloff <ingo.rohloff@lauterbach.com>
> ---
> drivers/usb/gadget/function/f_fs.c | 269 ++++++++++++++++++++++++++++-
> drivers/usb/gadget/function/u_fs.h | 4 +
> 2 files changed, 267 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
> index 7461d27e9604..a2e46704426f 100644
> --- a/drivers/usb/gadget/function/f_fs.c
> +++ b/drivers/usb/gadget/function/f_fs.c
> @@ -201,6 +201,23 @@ struct ffs_epfile {
> unsigned char _pad;
> };
>
> +struct ffs_ep_listener {
> + struct ffs_epfile *epfile;
> + struct list_head ffsm_list;
> + spinlock_t ffsm_lock;
> +};
> +
> +struct ffs_memory {
> + struct list_head memlist;
> + struct ffs_ep_listener *listener;
> + char *kmem;
> + unsigned long vm_start;
> + u32 size;
> +
> + int vma_use_count;
> + int aio_use_count;
> +};
> +
> struct ffs_buffer {
> size_t length;
> char *data;
> @@ -227,6 +244,7 @@ struct ffs_io_data {
> bool use_sg;
>
> struct ffs_data *ffs;
> + struct ffs_memory *ffsm;
> };
>
> struct ffs_desc_helper {
> @@ -702,6 +720,200 @@ static const struct file_operations ffs_ep0_operations = {
> .poll = ffs_ep0_poll,
> };
>
> +/* Handling of mmapped transfers *******************************/
> +
> +/* Check whether it's okay to allocate more memory for mmap */
> +static int ffsm_increase_mmap_mem_usage(struct ffs_data *ffs, u64 amount)
> +{
> + u64 lim;
> +
> + lim = READ_ONCE(ffs->mmap_memory_mb);
> + lim <<= 20;
> +
> + atomic64_add(amount, &ffs->mmap_mem_usage);
> +
> + if (lim > 0 && atomic64_read(&ffs->mmap_mem_usage) > lim) {
What prevents it from changing right after you read this?
> + atomic64_sub(amount, &ffs->mmap_mem_usage);
Why not use a real lock instead of trying to do a fake one with this
atomic variable? You are not really protecting anything here correctly
from what I can tell.
thanks,
greg k-h
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 1/1] usb: gadget: f_fs: Support zerocopy transfers via mmap.
2022-02-08 10:44 ` Greg KH
@ 2022-02-08 11:48 ` Ingo Rohloff
2022-02-08 15:21 ` Alan Stern
0 siblings, 1 reply; 6+ messages in thread
From: Ingo Rohloff @ 2022-02-08 11:48 UTC (permalink / raw)
To: Greg KH; +Cc: balbi, linux-usb
Hello Greg,
On Tue, 8 Feb 2022 11:44:27 +0100
Greg KH <gregkh@linuxfoundation.org> wrote:
> On Wed, Feb 02, 2022 at 06:20:56PM +0100, Ingo Rohloff wrote:
> > This patch implements the same functionality for FunctionFS as
> > commit f7d34b445abc00e979b7 ("USB: Add support for usbfs zerocopy.")
> > did for USB host devio.c
> ...
> > +/* Check whether it's okay to allocate more memory for mmap */
> > +static int ffsm_increase_mmap_mem_usage(struct ffs_data *ffs, u64 amount)
> > +{
> > + u64 lim;
> > +
> > + lim = READ_ONCE(ffs->mmap_memory_mb);
> > + lim <<= 20;
> > +
> > + atomic64_add(amount, &ffs->mmap_mem_usage);
> > +
> > + if (lim > 0 && atomic64_read(&ffs->mmap_mem_usage) > lim) {
>
> What prevents it from changing right after you read this?
Nothing.
First of all: I just used the same code as in "drivers/usb/core/devio.c"
functions "usbfs_increase_memory_usage()" and "usbfs_decrease_memory_usage()".
As far as I understand the code of these two functions, this code to imposes a
limit on the amount of kernel space memory, a user might allocate via "mmap"
calls.
The construction makes sure that when "ffsm_increase_mmap_mem_usage()" returns
successfully, it is guaranteed, that "mmap_mem_usage" *was* smaller/equal than
"lim" at the time the atomic64_read() call was done.
Of course "mmap_mem_usage" might change immediately after the atomic64_read().
But as far as I analyzed, this still limits the total amount of memory
allocated, as long as you make sure that you do the allocation of memory
*after* "ffsm_increase_mmap_mem_usage()" returned successfully and you
deallocate the memory *before* you call "ffsm_decrease_mmap_mem_usage()".
> > + atomic64_sub(amount, &ffs->mmap_mem_usage);
>
> Why not use a real lock instead of trying to do a fake one with this
> atomic variable?
I don't think there is a good reason using the "atomic" stuff:
I think this code path anyway is not hit that often (only when you mmap or
munmap buffers), so this should not have any noticeable impact on performance.
I just took the code from "drivers/usb/core/devio.c",
"usbfs_increase_memory_usage()".
I am still convinced it is correct.
You are of course right: You can easily use a lock here and this makes the
intention of the code a lot clearer I guess.
I will modify the patch accordingly.
so long
Ingo
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 1/1] usb: gadget: f_fs: Support zerocopy transfers via mmap.
2022-02-08 11:48 ` Ingo Rohloff
@ 2022-02-08 15:21 ` Alan Stern
0 siblings, 0 replies; 6+ messages in thread
From: Alan Stern @ 2022-02-08 15:21 UTC (permalink / raw)
To: Ingo Rohloff; +Cc: Greg KH, balbi, linux-usb
On Tue, Feb 08, 2022 at 12:48:17PM +0100, Ingo Rohloff wrote:
> > > + atomic64_sub(amount, &ffs->mmap_mem_usage);
> >
> > Why not use a real lock instead of trying to do a fake one with this
> > atomic variable?
>
> I don't think there is a good reason using the "atomic" stuff:
> I think this code path anyway is not hit that often (only when you mmap or
> munmap buffers), so this should not have any noticeable impact on performance.
>
> I just took the code from "drivers/usb/core/devio.c",
> "usbfs_increase_memory_usage()".
> I am still convinced it is correct.
>
> You are of course right: You can easily use a lock here and this makes the
> intention of the code a lot clearer I guess.
>
> I will modify the patch accordingly.
If you also feel like making a similar change to the code in devio.c, it
would be welcome.
Alan Stern
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 1/1] usb: gadget: f_fs: Support zerocopy transfers via mmap.
@ 2022-02-12 18:17 kernel test robot
0 siblings, 0 replies; 6+ messages in thread
From: kernel test robot @ 2022-02-12 18:17 UTC (permalink / raw)
To: kbuild
[-- Attachment #1: Type: text/plain, Size: 23257 bytes --]
CC: llvm(a)lists.linux.dev
CC: kbuild-all(a)lists.01.org
In-Reply-To: <20220202172056.44722-2-ingo.rohloff@lauterbach.com>
References: <20220202172056.44722-2-ingo.rohloff@lauterbach.com>
TO: Ingo Rohloff <ingo.rohloff@lauterbach.com>
TO: gregkh(a)linuxfoundation.org
TO: balbi(a)kernel.org
CC: linux-usb(a)vger.kernel.org
CC: Ingo Rohloff <ingo.rohloff@lauterbach.com>
Hi Ingo,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on usb/usb-testing]
[also build test WARNING on v5.17-rc3 next-20220211]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]
url: https://github.com/0day-ci/linux/commits/Ingo-Rohloff/Zerocopy-for-USB-Gadget-FunctionFS/20220203-012919
base: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git usb-testing
:::::: branch date: 10 days ago
:::::: commit date: 10 days ago
config: riscv-randconfig-c006-20220205 (https://download.01.org/0day-ci/archive/20220212/202202122302.z3tLgceb-lkp(a)intel.com/config)
compiler: clang version 15.0.0 (https://github.com/llvm/llvm-project dee058c670593b999fec19c458dbbd882ad9de56)
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# install riscv cross compiling tool for clang build
# apt-get install binutils-riscv64-linux-gnu
# https://github.com/0day-ci/linux/commit/dee77498ca5c303beb5ef64b95072fea55d6267f
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Ingo-Rohloff/Zerocopy-for-USB-Gadget-FunctionFS/20220203-012919
git checkout dee77498ca5c303beb5ef64b95072fea55d6267f
# save the config file to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=riscv clang-analyzer
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
clang-analyzer warnings: (new ones prefixed by >>)
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
11 warnings generated.
drivers/w1/w1.c:997:2: warning: Value stored to 'search_bit' is never read [clang-analyzer-deadcode.DeadStores]
search_bit = 0;
^ ~
drivers/w1/w1.c:997:2: note: Value stored to 'search_bit' is never read
search_bit = 0;
^ ~
drivers/w1/w1.c:999:2: warning: Value stored to 'last_rn' is never read [clang-analyzer-deadcode.DeadStores]
last_rn = 0;
^ ~
drivers/w1/w1.c:999:2: note: Value stored to 'last_rn' is never read
last_rn = 0;
^ ~
Suppressed 9 warnings (2 in non-user code, 7 with check filters).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
9 warnings generated.
Suppressed 9 warnings (2 in non-user code, 7 with check filters).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
2 warnings generated.
Suppressed 2 warnings (2 in non-user code).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
9 warnings generated.
Suppressed 9 warnings (2 in non-user code, 7 with check filters).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
9 warnings generated.
Suppressed 9 warnings (2 in non-user code, 7 with check filters).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
2 warnings generated.
Suppressed 2 warnings (2 in non-user code).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
9 warnings generated.
Suppressed 9 warnings (2 in non-user code, 7 with check filters).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
6 warnings generated.
drivers/w1/slaves/w1_therm.c:159:8: warning: Excessive padding in 'struct w1_therm_family_converter' (12 padding bytes, where 4 is optimal).
Optimal fields order:
f,
convert,
get_conversion_time,
set_resolution,
get_resolution,
write_data,
reserved,
broken,
bulk_read,
consider reordering the fields or adding explicit padding members [clang-analyzer-optin.performance.Padding]
struct w1_therm_family_converter {
~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/w1/slaves/w1_therm.c:159:8: note: Excessive padding in 'struct w1_therm_family_converter' (12 padding bytes, where 4 is optimal). Optimal fields order: f, convert, get_conversion_time, set_resolution, get_resolution, write_data, reserved, broken, bulk_read, consider reordering the fields or adding explicit padding members
struct w1_therm_family_converter {
~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/w1/slaves/w1_therm.c:1252:5: warning: Value stored to 'ret' is never read [clang-analyzer-deadcode.DeadStores]
ret = -EIO;
^ ~~~~
drivers/w1/slaves/w1_therm.c:1252:5: note: Value stored to 'ret' is never read
ret = -EIO;
^ ~~~~
drivers/w1/slaves/w1_therm.c:1799:2: warning: Call to function 'strcpy' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcpy'. CWE-119 [clang-analyzer-security.insecureAPI.strcpy]
strcpy(p_args, buf);
^~~~~~
drivers/w1/slaves/w1_therm.c:1799:2: note: Call to function 'strcpy' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcpy'. CWE-119
strcpy(p_args, buf);
^~~~~~
drivers/w1/slaves/w1_therm.c:2089:22: warning: The right operand of '==' is a garbage value [clang-analyzer-core.UndefinedBinaryOperatorResult]
if (sl->reg_num.id == reg_num->id)
^ ~~~~~~~~~~~
drivers/w1/slaves/w1_therm.c:2066:6: note: Assuming the condition is false
if (w1_reset_bus(sl->master))
^~~~~~~~~~~~~~~~~~~~~~~~
drivers/w1/slaves/w1_therm.c:2066:2: note: Taking false branch
if (w1_reset_bus(sl->master))
^
drivers/w1/slaves/w1_therm.c:2076:6: note: Assuming 'ack' is equal to W1_42_SUCCESS_CONFIRM_BYTE
if (ack != W1_42_SUCCESS_CONFIRM_BYTE)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/w1/slaves/w1_therm.c:2076:2: note: Taking false branch
if (ack != W1_42_SUCCESS_CONFIRM_BYTE)
^
drivers/w1/slaves/w1_therm.c:2080:2: note: Loop condition is true. Entering loop body
for (i = 0; i <= 64; i++) {
^
drivers/w1/slaves/w1_therm.c:2081:7: note: Assuming the condition is false
if (w1_reset_bus(sl->master))
^~~~~~~~~~~~~~~~~~~~~~~~
drivers/w1/slaves/w1_therm.c:2081:3: note: Taking false branch
if (w1_reset_bus(sl->master))
^
drivers/w1/slaves/w1_therm.c:2087:7: note: Assuming field 'family' is not equal to W1_42_FINISHED_BYTE
if (reg_num->family == W1_42_FINISHED_BYTE)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/w1/slaves/w1_therm.c:2087:3: note: Taking false branch
if (reg_num->family == W1_42_FINISHED_BYTE)
^
drivers/w1/slaves/w1_therm.c:2089:22: note: The right operand of '==' is a garbage value
if (sl->reg_num.id == reg_num->id)
^ ~~~~~~~~~~~
Suppressed 2 warnings (2 in non-user code).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
10 warnings generated.
>> drivers/usb/gadget/function/f_fs.c:866:2: warning: Value stored to 'ret' is never read [clang-analyzer-deadcode.DeadStores]
ret = 0;
^ ~
drivers/usb/gadget/function/f_fs.c:866:2: note: Value stored to 'ret' is never read
ret = 0;
^ ~
Suppressed 9 warnings (2 in non-user code, 7 with check filters).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
10 warnings generated.
Suppressed 10 warnings (3 in non-user code, 7 with check filters).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
10 warnings generated.
Suppressed 10 warnings (3 in non-user code, 7 with check filters).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
10 warnings generated.
Suppressed 10 warnings (3 in non-user code, 7 with check filters).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
10 warnings generated.
Suppressed 10 warnings (3 in non-user code, 7 with check filters).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
11 warnings generated.
drivers/usb/gadget/function/uvc_configfs.c:2037:30: warning: Value stored to 'u' during its initialization is never read [clang-analyzer-deadcode.DeadStores]
struct uvcg_uncompressed *u =
^
drivers/usb/gadget/function/uvc_configfs.c:2037:30: note: Value stored to 'u' during its initialization is never read
struct uvcg_uncompressed *u =
^
drivers/usb/gadget/function/uvc_configfs.c:2043:23: warning: Value stored to 'm' during its initialization is never read [clang-analyzer-deadcode.DeadStores]
struct uvcg_mjpeg *m =
^
drivers/usb/gadget/function/uvc_configfs.c:2043:23: note: Value stored to 'm' during its initialization is never read
struct uvcg_mjpeg *m =
^
Suppressed 9 warnings (2 in non-user code, 7 with check filters).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
9 warnings generated.
Suppressed 9 warnings (2 in non-user code, 7 with check filters).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
9 warnings generated.
Suppressed 9 warnings (2 in non-user code, 7 with check filters).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
9 warnings generated.
Suppressed 9 warnings (2 in non-user code, 7 with check filters).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
12 warnings generated.
drivers/usb/gadget/legacy/ether.c:373:20: warning: Access to field 'bound' results in a dereference of a null pointer (loaded from variable 'eem_opts') [clang-analyzer-core.NullDereference]
eem_opts->bound = true;
~~~~~~~~ ^
drivers/usb/gadget/legacy/ether.c:307:2: note: 'eem_opts' initialized to a null pointer value
struct f_eem_opts *eem_opts = NULL;
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/usb/gadget/legacy/ether.c:314:6: note: Assuming 'use_eem' is false
if (use_eem) {
^~~~~~~
drivers/usb/gadget/legacy/ether.c:314:2: note: Taking false branch
if (use_eem) {
^
drivers/usb/gadget/legacy/ether.c:327:13: note: Calling 'can_support_ecm'
} else if (can_support_ecm(gadget)) {
^~~~~~~~~~~~~~~~~~~~~~~
drivers/usb/gadget/function/u_ether.h:268:7: note: Calling 'gadget_is_altset_supported'
if (!gadget_is_altset_supported(gadget))
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/usb/gadget.h:523:9: note: Assuming field 'quirk_altset_not_supp' is 0, which participates in a condition later
return !g->quirk_altset_not_supp;
^~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/usb/gadget.h:523:2: note: Returning without writing to 'g->quirk_altset_not_supp', which participates in a condition later
return !g->quirk_altset_not_supp;
^
include/linux/usb/gadget.h:523:2: note: Returning the value 1, which participates in a condition later
return !g->quirk_altset_not_supp;
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/usb/gadget/function/u_ether.h:268:7: note: Returning from 'gadget_is_altset_supported'
if (!gadget_is_altset_supported(gadget))
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/usb/gadget/function/u_ether.h:268:2: note: Taking false branch
if (!gadget_is_altset_supported(gadget))
^
drivers/usb/gadget/function/u_ether.h:275:2: note: Returning the value 1, which participates in a condition later
return true;
^~~~~~~~~~~
drivers/usb/gadget/legacy/ether.c:327:13: note: Returning from 'can_support_ecm'
} else if (can_support_ecm(gadget)) {
^~~~~~~~~~~~~~~~~~~~~~~
drivers/usb/gadget/legacy/ether.c:327:9: note: Taking true branch
} else if (can_support_ecm(gadget)) {
^
drivers/usb/gadget/legacy/ether.c:331:7: note: Calling 'IS_ERR'
if (IS_ERR(fi_ecm))
^~~~~~~~~~~~~~
include/linux/err.h:36:9: note: Assuming the condition is false
return IS_ERR_VALUE((unsigned long)ptr);
^
include/linux/err.h:22:34: note: expanded from macro 'IS_ERR_VALUE'
#define IS_ERR_VALUE(x) unlikely((unsigned long)(void *)(x) >= (unsigned long)-MAX_ERRNO)
~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/compiler.h:48:41: note: expanded from macro 'unlikely'
# define unlikely(x) (__branch_check__(x, 0, __builtin_constant_p(x)))
~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/compiler.h:33:34: note: expanded from macro '__branch_check__'
______r = __builtin_expect(!!(x), expect); \
vim +/ret +866 drivers/usb/gadget/function/f_fs.c
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 847
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 848 static int ffs_epfile_mmap(struct file *file, struct vm_area_struct *vma)
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 849 {
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 850 struct ffs_ep_listener *listener = file->private_data;
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 851 struct ffs_memory *ffsm = NULL;
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 852 size_t size = vma->vm_end - vma->vm_start;
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 853 char *kmem;
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 854 int rc, ret;
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 855
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 856 if (!IS_ALIGNED(size, PAGE_SIZE))
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 857 return -EFAULT;
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 858
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 859 rc = ffsm_increase_mmap_mem_usage(
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 860 listener->epfile->ffs,
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 861 size + sizeof(struct ffs_memory)
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 862 );
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 863 if (rc)
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 864 return -ENOMEM;
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 865
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 @866 ret = 0;
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 867 ffsm = kzalloc(sizeof(struct ffs_memory), GFP_KERNEL);
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 868 if (!ffsm) {
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 869 ret = -ENOMEM;
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 870 goto error_decrease_mem;
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 871 }
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 872
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 873 kmem = kzalloc(size, GFP_USER | __GFP_NOWARN);
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 874 if (!kmem) {
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 875 kfree(ffsm);
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 876 ret = -ENOMEM;
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 877 goto error_decrease_mem;
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 878 }
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 879
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 880 rc = remap_pfn_range(
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 881 vma,
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 882 vma->vm_start,
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 883 PHYS_PFN(virt_to_phys(kmem)),
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 884 size,
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 885 vma->vm_page_prot
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 886 );
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 887 if (rc < 0) {
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 888 kfree(kmem);
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 889 kfree(ffsm);
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 890 ret = -EAGAIN;
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 891 goto error_decrease_mem;
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 892 }
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 893
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 894
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 895 INIT_LIST_HEAD(&ffsm->memlist);
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 896 ffsm->listener = listener;
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 897 ffsm->kmem = kmem;
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 898 ffsm->vm_start = vma->vm_start;
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 899 ffsm->size = size;
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 900 ffsm->vma_use_count = 1;
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 901
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 902 vma->vm_ops = &ffsm_vm_ops;
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 903 vma->vm_private_data = ffsm;
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 904
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 905 spin_lock_irq(&listener->ffsm_lock);
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 906 list_add_tail(&ffsm->memlist, &listener->ffsm_list);
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 907 spin_unlock_irq(&listener->ffsm_lock);
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 908 return 0;
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 909
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 910 error_decrease_mem:
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 911 ffsm_decrease_mmap_mem_usage(
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 912 listener->epfile->ffs,
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 913 size + sizeof(struct ffs_memory)
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 914 );
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 915 return ret;
dee77498ca5c30 drivers/usb/gadget/function/f_fs.c Ingo Rohloff 2022-02-02 916 }
ddf8abd2599491 drivers/usb/gadget/f_fs.c Michal Nazarewicz 2010-05-05 917
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2022-02-12 18:17 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-02-02 17:20 [PATCH v2 0/1] Zerocopy for USB Gadget FunctionFS Ingo Rohloff
2022-02-02 17:20 ` [PATCH v2 1/1] usb: gadget: f_fs: Support zerocopy transfers via mmap Ingo Rohloff
2022-02-08 10:44 ` Greg KH
2022-02-08 11:48 ` Ingo Rohloff
2022-02-08 15:21 ` Alan Stern
-- strict thread matches above, loose matches on Subject: below --
2022-02-12 18:17 kernel test robot
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.