usb-storage: fsync() take too much time when handing ALLOW_MEDIUM_REMOVAL

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

 



Hi,
  I have one slow flash block device, which act as usb-mass storage
device, and during the data transfer with windows PC, it will get
ALLOW_MEDIUM_REMOVAL , and sync the file system cache, however, it
takes too much time (by log about 10s) and the usb reset occurs.
however, if the /proc/sys/vm_dirty_ratio changed from 20 to 0 or 4,
everything is ok.
  I made some code change to defer the file cache flash for your
review, currently the do_verify() and do_synchronize_cache() not
touched.

diff --git a/drivers/usb/gadget/f_mass_storage.c
b/drivers/usb/gadget/f_mass_storage.c
index b02ff32..7ddcc5c 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -1491,6 +1491,14 @@ static int do_start_stop(struct fsg_common *common)
 		: 0;
 }

+void fsg_lun_fsync_deferred_func(struct work_struct *work)
+{
+	struct fsg_lun	*curlun =
+		container_of(work, struct fsg_lun, fsync_deferred_work);
+	
+	fsg_lun_fsync_sub(curlun);
+}
+
 static int do_prevent_allow(struct fsg_common *common)
 {
 	struct fsg_lun	*curlun = common->curlun;
@@ -1510,7 +1518,7 @@ static int do_prevent_allow(struct fsg_common *common)
 	}

 	if (curlun->prevent_medium_removal && !prevent)
-		fsg_lun_fsync_sub(curlun);
+		schedule_work(&curlun->fsync_deferred_work);
 	curlun->prevent_medium_removal = prevent;
 	return 0;
 }
@@ -2835,6 +2843,8 @@ static struct fsg_common *fsg_common_init(struct
fsg_common *common,
 			   ? cfg->lun_name_format
 			   : "lun%d",
 			     i);
+		INIT_WORK(&curlun->fsync_deferred_work,
+				fsg_lun_fsync_deferred_func);

 		rc = device_register(&curlun->dev);
 		if (rc) {
diff --git a/drivers/usb/gadget/file_storage.c
b/drivers/usb/gadget/file_storage.c
index 0333cc5..c7266c0 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -1853,6 +1853,13 @@ static int do_start_stop(struct fsg_dev *fsg)
 	return 0;
 }

+void fsg_lun_fsync_deferred_func(struct work_struct *work)
+{
+	struct fsg_lun	*curlun =
+		container_of(work, struct fsg_lun, fsync_deferred_work);
+	
+	fsg_lun_fsync_sub(curlun);
+}

 static int do_prevent_allow(struct fsg_dev *fsg)
 {
@@ -1871,7 +1878,7 @@ static int do_prevent_allow(struct fsg_dev *fsg)
 	}

 	if (curlun->prevent_medium_removal && !prevent)
-		fsg_lun_fsync_sub(curlun);
+		schedule_work(&curlun->fsync_deferred_work);
 	curlun->prevent_medium_removal = prevent;
 	return 0;
 }
@@ -3420,6 +3427,8 @@ static int __init fsg_bind(struct usb_gadget *gadget)
 		dev_set_drvdata(&curlun->dev, &fsg->filesem);
 		dev_set_name(&curlun->dev,"%s-lun%d",
 			     dev_name(&gadget->dev), i);
+		INIT_WORK(&curlun->fsync_deferred_work,
+				fsg_lun_fsync_deferred_func);

 		kref_get(&fsg->ref);
 		rc = device_register(&curlun->dev);
diff --git a/drivers/usb/gadget/storage_common.c
b/drivers/usb/gadget/storage_common.c
index 840a4be..16bcb3d 100644
--- a/drivers/usb/gadget/storage_common.c
+++ b/drivers/usb/gadget/storage_common.c
@@ -250,6 +250,7 @@ struct fsg_lun {
 	unsigned int	blkbits;	/* Bits of logical block size */
 	unsigned int	blksize;	/* logic block size of backing device */
 	struct device	dev;
+	struct work_struct fsync_deferred_work;
 };

 #define fsg_lun_is_open(curlun)	((curlun)->filp != NULL)


thanks
Yuping Luo
--
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