diff options
author | Arpad Horvath <secracon@gmail.com> | 2014-02-14 16:42:27 -0800 |
---|---|---|
committer | JP Abgrall <jpa@google.com> | 2014-02-14 16:50:27 -0800 |
commit | 80b435a3f35795600654e9705f4b3fbbcc427a9d (patch) | |
tree | 4dd4f4f5cb43c520464070a8a3188691f652fab9 /sdcard | |
parent | d0307beeef57b9db06b82f1ffba746c5decb0b72 (diff) |
sdcard: direct I/O file access fix
If a file is opened in direct I/O mode (with O_DIRECT flag),
the read buffer addess must be aligned to memory page size
boundary. The Direct I/O is not needed for normal files,
however, some special hardware access (e.g. smart SD cards)
will not work without it.
Change-Id: I42babeee86dba1880fd23e2592fddd7060da3e20
Diffstat (limited to 'sdcard')
-rw-r--r-- | sdcard/sdcard.c | 9 |
1 files changed, 5 insertions, 4 deletions
diff --git a/sdcard/sdcard.c b/sdcard/sdcard.c index 4722708f3..3bc8cd3f7 100644 --- a/sdcard/sdcard.c +++ b/sdcard/sdcard.c @@ -232,7 +232,7 @@ struct fuse_handler { * buffer at the same time. This allows us to share the underlying storage. */ union { __u8 request_buffer[MAX_REQUEST_SIZE]; - __u8 read_buffer[MAX_READ]; + __u8 read_buffer[MAX_READ + PAGESIZE]; }; }; @@ -1218,6 +1218,7 @@ static int handle_read(struct fuse* fuse, struct fuse_handler* handler, __u32 size = req->size; __u64 offset = req->offset; int res; + __u8 *read_buffer = (__u8 *) ((uintptr_t)(handler->read_buffer + PAGESIZE) & ~((uintptr_t)PAGESIZE-1)); /* Don't access any other fields of hdr or req beyond this point, the read buffer * overlaps the request buffer and will clobber data in the request. This @@ -1225,14 +1226,14 @@ static int handle_read(struct fuse* fuse, struct fuse_handler* handler, TRACE("[%d] READ %p(%d) %u@%llu\n", handler->token, h, h->fd, size, offset); - if (size > sizeof(handler->read_buffer)) { + if (size > MAX_READ) { return -EINVAL; } - res = pread64(h->fd, handler->read_buffer, size, offset); + res = pread64(h->fd, read_buffer, size, offset); if (res < 0) { return -errno; } - fuse_reply(fuse, unique, handler->read_buffer, res); + fuse_reply(fuse, unique, read_buffer, res); return NO_STATUS; } |