[RFC] USB: gadget: f_mass_storage: limit page cache usage

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This commit add code that flushed page cache disk buffers every 128 read
and write request. It has almost no impact on the performance of the
emulate usb drive but saves system page cache from being filled with
useless emulated disk data.

Signed-off-by: Marek Szyprowski <m.szyprowski@xxxxxxxxxxx>
Signed-off-by: Kyungmin Park <kyungmin.park@xxxxxxxxxxx>

---

Hello,

In the embedded system development we encoutered a really anoying
behaviour of USB mass storage gadget. We use it to export SD card as USB
disk. However when user copies a lot of data from or to the USB disk,
the mass storage gadget consumes almost all pages from system page
cache. This results in a significant degradation of system and io
performance. A lot of valid and really often used disk cache data is
wiped from memory and need to be constantly reloaded.

Caching mass storage backing file is usually useless. Host system very
rarely sends requests for the same blocks in the limited time window.
Usually there is another caching layer on the host system anyway.

Disabling page cache for the backing file is also not the solution,
because mmc perform really bad on direct 512 byte reads and writes.

I've did a quick hack to limit the amount of page cache that is being
used by mass storage gadget.  I've forced mass storage gadget to flush
and invalidate page cache once every 128 read or write request. I know
that the patch is ugly but it solves the issue.

Do you have any suggestion how to correctly introduce a method of
limiting page cache usage in the mass storage gadget? 

Best regards
--
Marek Szyprowski
Samsung Poland R&D Center

---
 drivers/usb/gadget/f_mass_storage.c |   28 ++++++++++++++++++++++++++++
 1 files changed, 28 insertions(+), 0 deletions(-)

diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index 7f585ac..3ffe1bd 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -729,6 +729,8 @@ static int sleep_thread(struct fsg_common *common)
 
 /*-------------------------------------------------------------------------*/
 
+static void invalidate_sub(struct fsg_lun *curlun);
+
 static int do_read(struct fsg_common *common)
 {
 	struct fsg_lun		*curlun = common->curlun;
@@ -740,6 +742,7 @@ static int do_read(struct fsg_common *common)
 	unsigned int		amount;
 	unsigned int		partial_page;
 	ssize_t			nread;
+	static int		counter;
 
 	/*
 	 * Get the starting Logical Block Address and check that it's
@@ -855,6 +858,18 @@ static int do_read(struct fsg_common *common)
 		common->next_buffhd_to_fill = bh->next;
 	}
 
+	if (++counter == 128) {
+		/* Write out all the dirty buffers before invalidating them */
+		fsg_lun_fsync_sub(curlun);
+		if (signal_pending(current))
+			return -EINTR;
+
+		invalidate_sub(curlun);
+		if (signal_pending(current))
+			return -EINTR;
+		counter = 0;
+	}
+
 	return -EIO;		/* No default reply */
 }
 
@@ -873,6 +888,7 @@ static int do_write(struct fsg_common *common)
 	unsigned int		partial_page;
 	ssize_t			nwritten;
 	int			rc;
+	static int		counter;
 
 	if (curlun->ro) {
 		curlun->sense_data = SS_WRITE_PROTECTED;
@@ -1055,6 +1071,18 @@ static int do_write(struct fsg_common *common)
 			return rc;
 	}
 
+	if (++counter == 128) {
+		/* Write out all the dirty buffers before invalidating them */
+		fsg_lun_fsync_sub(curlun);
+		if (signal_pending(current))
+			return -EINTR;
+
+		invalidate_sub(curlun);
+		if (signal_pending(current))
+			return -EINTR;
+		counter = 0;
+	}
+
 	return -EIO;		/* No default reply */
 }
 
-- 
1.7.1.569.g6f426

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux