mmap(2): do not read entire file
@@ -171,35 +171,33 @@ static sysreturn mincore(void *addr, u64 length, u8 *vec)
return -ENOMEM;
}
-CLOSURE_4_1(mmap_load_entire, void, thread, u64, u64, u64, buffer);
-void mmap_load_entire(thread t, u64 where, u64 len, u64 offset, buffer b) {
+CLOSURE_4_2(mmap_read_complete, void, thread, u64, u64, buffer, status, bytes);
+void mmap_read_complete(thread t, u64 where, u64 mmap_len, buffer b, status s, bytes length) {
+ if (!is_ok(s)) {
+ deallocate_buffer(b);
+ set_syscall_error(t, EACCES);
+ thread_wakeup(t);
+ return;
+ }
+
kernel_heaps kh = (kernel_heaps)&t->uh;
heap pages = heap_pages(kh);
heap physical = heap_physical(kh);
- u64 msize = 0;
- u64 blen = buffer_length(b);
- if (blen > offset)
- msize = pad(blen - offset, PAGESIZE);
- if (msize > len)
- msize = len;
-
// mutal misalignment?...discontiguous backing?
- u64 p = physical_from_virtual(buffer_ref(b, offset));
- map(where, p, msize, pages);
+ u64 length_padded = pad(length, PAGESIZE);
+ u64 p = physical_from_virtual(buffer_ref(b, 0));
+ map(where, p, length_padded, pages);
+ if (length < length_padded)
+ zero(pointer_from_u64(where + length), length_padded - length);
- if (len > msize) {
- u64 bss = pad(len, PAGESIZE) - msize;
- map(where + msize, allocate_u64(physical, bss), bss, pages);
- zero(pointer_from_u64(where + msize), bss);
- }
- set_syscall_return(t, where);
- thread_wakeup(t);
+ if (length_padded < mmap_len) {
+ u64 bss = pad(mmap_len, PAGESIZE) - length_padded;
+ map(where + length_padded, allocate_u64(physical, bss), bss, pages);
+ zero(pointer_from_u64(where + length_padded), bss);
}
-CLOSURE_1_1(mmap_load_entire_fail, void, thread, status);
-void mmap_load_entire_fail(thread t, status v) {
- set_syscall_error(t, EACCES);
+ set_syscall_return(t, where);
thread_wakeup(t);
}
@@ -330,9 +328,11 @@ static sysreturn mmap(void *target, u64 size, int prot, int flags, int fd, u64 o
file f = resolve_fd(current->p, fd);
thread_log(current, " read file, blocking...");
- filesystem_read_entire(p->fs, f->n, heap_backed(kh),
- closure(h, mmap_load_entire, current, where, len, offset),
- closure(h, mmap_load_entire_fail, current));
+
+ heap mh = heap_backed(kh);
+ buffer b = allocate_buffer(mh, pad(len, mh->pagesize));
+ filesystem_read(p->fs, f->n, buffer_ref(b, 0), len, offset,
+ closure(h, mmap_read_complete, current, where, len, b));
runloop();
}
