From: Dongwoo Lee Date: Fri, 26 Oct 2018 01:41:41 +0000 (+0900) Subject: usb: gadget: f_fs: Prevent panic due to failure of huge size buffer allocation X-Git-Tag: accepted/tizen/unified/20240422.153132~22 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b41b3fbde09786012a4ecfc0784ccfcfb6e32bbd;p=platform%2Fkernel%2Flinux-rpi.git usb: gadget: f_fs: Prevent panic due to failure of huge size buffer allocation The f_fs daemons usually use large size buffer for increasing transfer performance, but it can cause memory allocation failure in case of that buddy space is fragmented. Since this, instead of just returning error in this case, give the chance to retry to allocate memory with a half length in order to prevent daemon crash due to failure of buffer allocation. Signed-off-by: Dongwoo Lee [hoegeun.kwon: rebased and resolved conflicts] Signed-off-by: Hoegeun Kwon Signed-off-by: Marek Szyprowski Change-Id: Ief5f8256b37b38de14bb333e53c4c4688867d4f6 --- diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 6e9ef35..b32b66d 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -799,7 +799,7 @@ static inline void *ffs_alloc_buffer(struct ffs_io_data *io_data, if (io_data->use_sg) return ffs_build_sg_list(&io_data->sgt, data_len); - return kmalloc(data_len, GFP_KERNEL); + return kmalloc(data_len, GFP_KERNEL | __GFP_NOWARN); } static inline void ffs_free_buffer(struct ffs_io_data *io_data) @@ -1010,10 +1010,35 @@ 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); +retry_malloc: data = ffs_alloc_buffer(io_data, data_len); if (!data) { - ret = -ENOMEM; - goto error_mutex; + /* If usb gadget device using physically contiguous + * buffer f_fs daemons usually use large size buffer for + * performance. However, this can cause failure of + * kmalloc() due to buddy fragmentation, even if there + * is available memory and thus it can be compacted by + * kswapd. Therefore, instead of just returning error + * to daemon in the case of failure of kmalloc(), give + * the second chance to allocate buffer with a half size + * until it really fails due to memory shortage. + * Otherwise, return error when scatter-gather list. + */ + if (data_len <= PAGE_SIZE || io_data->use_sg) { + ret = -ENOMEM; + goto error_mutex; + } + + data_len = data_len >> 1; + + if (io_data->read) { + spin_lock_irq(&epfile->ffs->eps_lock); + data_len = usb_ep_align_maybe(gadget, + ep->ep, data_len); + spin_unlock_irq(&epfile->ffs->eps_lock); + } + + goto retry_malloc; } if (!io_data->read && !copy_from_iter_full(data, data_len, &io_data->data)) {