VFS: update filp_pos on chardev I/O (workaround)
Previously, reading from or writing to a character device would not update the file position on the corresponding filp object. Performing this update correctly is not trivial: during and after the I/O operation, the filp object must not be locked. Ideally, read/write requests on a filp that is already involved in a read/write operation, should be queued. For now, we optimistically update the file position at the start of the I/O; this works under the assumptions listed in the corresponding comment. Change-Id: I172a61781850423709924390ae3df1f2d1f94707
This commit is contained in:
parent
660d34cd85
commit
5c53b417cd
1 changed files with 23 additions and 1 deletions
|
@ -177,9 +177,31 @@ int read_write(struct fproc *rfp, int rw_flag, struct filp *f,
|
|||
r = dev_io(op, dev, for_e, buf, position, size, f->filp_flags,
|
||||
suspend_reopen);
|
||||
if (r >= 0) {
|
||||
/* This should no longer happen: all calls are asynchronous. */
|
||||
printf("VFS: I/O to device %x succeeded immediately!?\n", dev);
|
||||
cum_io = r;
|
||||
position += cum_io;
|
||||
position += r;
|
||||
r = OK;
|
||||
} else if (r == SUSPEND) {
|
||||
/* FIXME: multiple read/write operations on a single filp
|
||||
* should be serialized. They currently aren't; in order to
|
||||
* achieve a similar effect, we optimistically advance the file
|
||||
* position here. This works under the following assumptions:
|
||||
* - character drivers that use the seek position at all,
|
||||
* expose a view of a statically-sized range of bytes, i.e.,
|
||||
* they are basically byte-granular block devices;
|
||||
* - if short I/O or an error is returned, all subsequent calls
|
||||
* will return (respectively) EOF and an error;
|
||||
* - the application never checks its own file seek position,
|
||||
* or does not care that it may end up having seeked beyond
|
||||
* the number of bytes it has actually read;
|
||||
* - communication to the character driver is FIFO (this one
|
||||
* is actually true! whew).
|
||||
* Many improvements are possible here, but in the end,
|
||||
* anything short of queuing concurrent operations will be
|
||||
* suboptimal - so we settle for this hack for now.
|
||||
*/
|
||||
position += size;
|
||||
}
|
||||
} else if (S_ISBLK(vp->v_mode)) { /* Block special files. */
|
||||
if (vp->v_sdev == NO_DEV)
|
||||
|
|
Loading…
Reference in a new issue