Re: mass storage error reporting

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

 



On Tue, 25 Jan 2011, Yauheni Kaliuta wrote:

> Hi!
> 
> On Tue, Jan 25, 2011 at 10:02 PM, Alan Stern <stern@xxxxxxxxxxxxxxxxxxx> wrote:
> > On Tue, 25 Jan 2011, Yauheni Kaliuta wrote:
> >
> >> Hi!
> >>
> >> file_storage.c has the following code in do_write():
> 
> [...]
> 
> >>                         /* If an error occurred, report it and its position */
> >>                         if (nwritten < amount) {
> >>                                 curlun->sense_data = SS_WRITE_ERROR;
> >>                                 curlun->sense_data_info = file_offset >> 9;
> >>                                 curlun->info_valid = 1;
> >>                                 break;
> >>                         }
> >>
> >> In case of some data written (nwritten > 0), shouldn't it try to write
> >> the rest before error reporting?
> >
> > In theory, perhaps it should.  I haven't run across any situations
> > where nwritten was > 0 and < amount.  Likewise with reading.
> >
> 
> Well, I'm lucky enough to get it :) Not with the upstream code,
> however, but with custom read/write functions (which avoid vfs layer).

Here's a patch I wrote some time ago but never submitted because it 
didn't seem necessary.  It may need some adjustment before you can 
apply it to a current kernel.

Alan Stern



Index: usb-2.6/drivers/usb/gadget/file_storage.c
===================================================================
--- usb-2.6.orig/drivers/usb/gadget/file_storage.c
+++ usb-2.6/drivers/usb/gadget/file_storage.c
@@ -1132,7 +1132,7 @@ static int do_read(struct fsg_dev *fsg)
 	int			rc;
 	u32			amount_left;
 	loff_t			file_offset, file_offset_tmp;
-	unsigned int		amount;
+	unsigned int		amount, buf_offset;
 	unsigned int		partial_page;
 	ssize_t			nread;
 
@@ -1200,10 +1200,12 @@ static int do_read(struct fsg_dev *fsg)
 			break;
 		}
 
+		buf_offset = 0;
+ continue_read:
 		/* Perform the read */
 		file_offset_tmp = file_offset;
 		nread = vfs_read(curlun->filp,
-				(char __user *) bh->buf,
+				buf_offset + (char __user *) bh->buf,
 				amount, &file_offset_tmp);
 		VLDBG(curlun, "file read %u @ %llu -> %d\n", amount,
 				(unsigned long long) file_offset,
@@ -1223,11 +1225,17 @@ static int do_read(struct fsg_dev *fsg)
 		file_offset  += nread;
 		amount_left  -= nread;
 		fsg->residue -= nread;
-		bh->inreq->length = nread;
+		buf_offset   += nread;
+		bh->inreq->length = buf_offset;
 		bh->state = BUF_STATE_FULL;
 
 		/* If an error occurred, report it and its position */
 		if (nread < amount) {
+			/* Continue after a partial read */
+			if (nread > 0) {
+				amount -= nread;
+				goto continue_read;
+			}
 			curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
 			curlun->sense_data_info = file_offset >> 9;
 			curlun->info_valid = 1;
@@ -1258,7 +1266,7 @@ static int do_write(struct fsg_dev *fsg)
 	int			get_some_more;
 	u32			amount_left_to_req, amount_left_to_write;
 	loff_t			usb_offset, file_offset, file_offset_tmp;
-	unsigned int		amount;
+	unsigned int		amount, buf_offset;
 	unsigned int		partial_page;
 	ssize_t			nwritten;
 	int			rc;
@@ -1387,10 +1395,12 @@ static int do_write(struct fsg_dev *fsg)
 				amount = curlun->file_length - file_offset;
 			}
 
+			buf_offset = 0;
+ continue_write:
 			/* Perform the write */
 			file_offset_tmp = file_offset;
 			nwritten = vfs_write(curlun->filp,
-					(char __user *) bh->buf,
+					buf_offset + (char __user *) bh->buf,
 					amount, &file_offset_tmp);
 			VLDBG(curlun, "file write %u @ %llu -> %d\n", amount,
 					(unsigned long long) file_offset,
@@ -1408,12 +1418,18 @@ static int do_write(struct fsg_dev *fsg)
 				nwritten -= (nwritten & 511);
 						// Round down to a block
 			}
-			file_offset += nwritten;
+			file_offset  += nwritten;
 			amount_left_to_write -= nwritten;
 			fsg->residue -= nwritten;
+			buf_offset   += nwritten;
 
 			/* If an error occurred, report it and its position */
 			if (nwritten < amount) {
+				/* Continue after a partial write */
+				if (nwritten > 0) {
+					amount -= nwritten;
+					goto continue_write;
+				}
 				curlun->sense_data = SS_WRITE_ERROR;
 				curlun->sense_data_info = file_offset >> 9;
 				curlun->info_valid = 1;

--
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