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