Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mmap: cannot map a file #1155

Closed
niewim19 opened this issue Sep 3, 2024 · 2 comments · Fixed by phoenix-rtos/phoenix-rtos-kernel#593
Closed

mmap: cannot map a file #1155

niewim19 opened this issue Sep 3, 2024 · 2 comments · Fixed by phoenix-rtos/phoenix-rtos-kernel#593

Comments

@niewim19
Copy link
Contributor

niewim19 commented Sep 3, 2024

I cannot map a file into memory using mmap(). Below is the test code that presents the issue, and outputs on Phoenix-RTOS (ia32-generic-qemu) and on Ubuntu 22.04:

/*
* This short demonstartes a problem with mmap-ing a file.
* 1) A new file is opened, 32 characters are written to it and it is closed.
* 2) A file is reopened and an attempt of mapping first 16 bytes of it is made
*/

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>

int main() {
	const char *filename = "filename.txt";
	const char *data = "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456"; // 32 characters

	// Create file and write 32 characters
	int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
	write(fd, data, 32);
	close(fd);

	// Map the first 16 bytes of the file
	fd = open(filename, O_RDONLY);
	void *map = mmap(NULL, 16, PROT_READ, MAP_PRIVATE, fd, 0);
	if (map == MAP_FAILED) {
		perror("mmap error:");
		exit(EXIT_FAILURE);
	}

	printf("Mapped first 16 bytes of '%s' successfully.\n", filename);

	munmap(map, 16);
	close(fd);
	return 0;
}

Phoenix-RTOS ia32-generic outputs:

mmap error:: ENOMEM

while Ubuntu 22.04 (with gcc 11.4.0) outputs:

Mapped first 16 bytes of 'filename.txt' successfully.

Issue was discovered during porting x264 (phoenix-rtos/phoenix-rtos-ports#84) which mmaps an input video file.

@niewim19
Copy link
Contributor Author

niewim19 commented Sep 4, 2024

I have traced the issue to calling mmap with size parameter being not multiple of page size.

The whole call stack (in kernel) is as follow: syscalls_sys_mmap()->vm_mmap()->_vm_mmap() and here it exits through the second condition in the following IF statement's OR:
`https://github.com/phoenix-rtos/phoenix-rtos-kernel/blob/2a3f1d1b23c7c52e2b655dad8cf625fc358b7131/vm/map.c#L507-L509

	if ((size == 0) || ((size & (SIZE_PAGE - 1)) != 0)) {
		return NULL;
	}

The condition of size being multiple of page size is not mentioned in our mmap documentation. addr and offset being multiple of page size are mentioned to be implementation defined, but not size.
https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/

@niewim19
Copy link
Contributor Author

niewim19 commented Sep 6, 2024

One more note: according to our documentation, mmap():

The system performs mapping operations over whole pages. Thus, while the parameter len need not meet a size or alignment constraint, the system shall include, in any mapping operation, any partial page specified by the address range starting at pa and continuing for len bytes.

which strongly implies that len parameter does not need to follow any alignment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant