pager_req_read: handle short read

Change-Id: Iff89046041e012a65c80a29b485ddbb636435dd0
This commit is contained in:
Dominique Martinet
2018-07-24 18:36:58 +09:00
committed by Dominique Martinet
parent c2e1b8d694
commit dc8d6b740c

View File

@ -1451,7 +1451,7 @@ out:
static int pager_req_read(ihk_os_t os, uintptr_t handle, off_t off, size_t size, uintptr_t rpa) static int pager_req_read(ihk_os_t os, uintptr_t handle, off_t off, size_t size, uintptr_t rpa)
{ {
ssize_t ss; ssize_t ss, n;
struct pager *pager; struct pager *pager;
struct file *file = NULL; struct file *file = NULL;
uintptr_t phys = -1; uintptr_t phys = -1;
@ -1464,7 +1464,8 @@ static int pager_req_read(ihk_os_t os, uintptr_t handle, off_t off, size_t size,
ss = down_interruptible(&pager_sem); ss = down_interruptible(&pager_sem);
if (ss) { if (ss) {
printk("pager_req_read(%lx,%lx,%lx,%lx): signaled. %ld\n", handle, off, size, rpa, ss); pr_debug("%s(%lx,%lx,%lx,%lx): signaled. %ld\n",
__func__, handle, off, size, rpa, ss);
goto out; goto out;
} }
@ -1479,15 +1480,16 @@ static int pager_req_read(ihk_os_t os, uintptr_t handle, off_t off, size_t size,
if (!file) { if (!file) {
ss = -EBADF; ss = -EBADF;
printk("pager_req_read(%lx,%lx,%lx,%lx):pager not found. %ld\n", handle, off, size, rpa, ss); pr_warn("%s(%lx,%lx,%lx,%lx):pager not found. %ld\n",
__func__, handle, off, size, rpa, ss);
goto out; goto out;
} }
phys = ihk_device_map_memory(dev, rpa, size); phys = ihk_device_map_memory(dev, rpa, size);
buf = ihk_device_map_virtual(dev, phys, size, NULL, 0); buf = ihk_device_map_virtual(dev, phys, size, NULL, 0);
if (!buf) { if (!buf) {
printk("%s: ERROR: invalid buffer address\n", pr_warn("%s: ERROR: invalid buffer address\n",
__FUNCTION__); __func__);
ss = -EINVAL; ss = -EINVAL;
goto out; goto out;
} }
@ -1495,25 +1497,31 @@ static int pager_req_read(ihk_os_t os, uintptr_t handle, off_t off, size_t size,
fs = get_fs(); fs = get_fs();
set_fs(KERNEL_DS); set_fs(KERNEL_DS);
pos = off; pos = off;
ss = vfs_read(file, buf, size, &pos); n = 0;
if ((ss != size) && (ss > 0)) { while (n < size) {
#ifdef POSTK_DEBUG_TEMP_FIX_12 /* clear_user() used by kernel area, fix */ if (pos != off + n) {
memset(buf + ss, 0, size - ss); pr_warn("%s: pos wrong? got %lld, expected %ld\n",
ss = size; __func__, pos, off+n);
#else /* POSTK_DEBUG_TEMP_FIX_12 */ pos = off + n;
if (clear_user(buf+ss, size-ss) == 0) {
ss = size;
} }
else { ss = vfs_read(file, buf + n, size - n, &pos);
ss = -EFAULT; if (ss < 0) {
break;
} }
#endif /* POSTK_DEBUG_TEMP_FIX_12 */ if (ss == 0) {
memset(buf + n, 0, size - n);
n = size;
break;
}
n += ss;
} }
set_fs(fs); set_fs(fs);
if (ss < 0) { if (ss < 0) {
printk("pager_req_read(%lx,%lx,%lx,%lx):pread failed. %ld\n", handle, off, size, rpa, ss); pr_warn("%s(%lx,%lx,%lx,%lx):pread failed. %ld\n",
__func__, handle, off, size, rpa, ss);
goto out; goto out;
} }
ss = n;
out: out:
if (buf) { if (buf) {