hostfs oddities
Hi there,
I noticed two little misfeatures in the hostfs file system. The first one is most certainly a bug, the second one might be functioning as intended.
1. If a file is held read-only by one process it cannot by creat()'ed by another one:
[root@localhost ~]# mount -t hostfs none /mnt
[root@localhost ~]# cd /mnt/tmp
[root@localhost tmp]# touch foo
[root@localhost tmp]# tail -f foo &
[1] 895
[root@localhost tmp]# > foo
-bash: foo: Invalid argument
[root@localhost tmp]# kill 895
[1]+ Terminated tail -f foo
[root@localhost tmp]# > foo
I tracked that problem down to the set_attr() function in hostfs_user.c:
It tries to ftruncate() the read-only file descriptor. The file should be re-opened writable before changing its length.
2. As long as a file is held open changes made outside the UML kernel (i.e. on the host side) may not be visible:
[root@localhost tmp]# tail -f foo &
[1] 897
# Host system: echo "Hello World" > /tmp/foo
[root@localhost tmp]# cat foo
[root@localhost tmp]# kill 897
[1]+ Terminated tail -f foo
[root@localhost tmp]# cat foo
Hello World
I guess this is some kind of caching effect, because strace shows that there is only a single read to the actual physical file. Maybe hostfs should check whether the outside file has changed and invalidate the cache if necessary.
Cheers,
Ingo
-------------------------------------------------------------------------
Sponsored by: SourceForge.net Community Choice Awards: VOTE NOW! Studies have shown that voting for your favorite open source project, along with a healthy diet, reduces your potential for chronic lameness and boredom. Vote Now at http://www.sourceforge.net/community/cca08
_______________________________________________
User-mode-linux-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel
Quoted 14 lines · Ingo van Lil
1. If a file is held read-only by one process it cannot by creat()'ed by another one:
[root@localhost ~]# mount -t hostfs none /mnt
[root@localhost ~]# cd/mnt/tmp
[root@localhost tmp]# touch foo
[root@localhost tmp]# tail -f foo &
[1] 895
[root@localhost tmp]# > foo
-bash: foo: Invalid argument
[root@localhost tmp]# kill 895
[1]+ Terminated tail -f foo
[root@localhost tmp]# > foo
Quoted 3 lines
I tracked that problem down to the
set_attr()function inhostfs_user.c:
It tries toftruncate()the read-only file descriptor. The file should be re-opened writable before changing its length.
Looks like a good diagnosis. There is code in host_file_open which is supposed to handle this case, but it's not being hit when the shell opens the file, which I don't understand.
Quoted 12 lines
2. As long as a file is held open changes made outside the UML kernel (i.e. on the host side) may not be visible:
[root@localhost tmp]# tail -f foo &
[1] 897
# Host system: echo "Hello World" >/tmp/foo
[root@localhost tmp]# cat foo
[root@localhost tmp]# kill 897
[1]+ Terminated tail -f foo
[root@localhost tmp]# cat foo
Hello World
Quoted 4 lines
I guess this is some kind of caching effect, because strace shows that there is only a single read to the actual physical file. Maybe hostfs should check whether the outside file has changed and invalidate the cache if necessary.
Correct. I've pondered using [id]notify to track changes on the host and either invalidate the UML cache or update it. Both involve interactions with the page cache that I'm not entirely comfortable with right now.
Jeff
Signature · 11 lines
Work email - jdike at linux dot intel dot com ------------------------------------------------------------------------- Sponsored by: SourceForge.net Community Choice Awards: VOTE NOW! Studies have shown that voting for your favorite open source project, along with a healthy diet, reduces your potential for chronic lameness and boredom. Vote Now at http://www.sourceforge.net/community/cca08 _______________________________________________ User-mode-linux-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel
Quoted 3 lines · Jeff Dike
Quoted 3 lines
1. If a file is held read-only by one process it cannot by creat()'ed by another one:
[...]
Quoted 8 lines
Quoted 4 lines
I tracked that problem down to the
set_attr()function inhostfs_user.c:
It tries toftruncate()the read-only file descriptor. The file should be re-opened writable before changing its length.Looks like a good diagnosis. There is code in
host_file_openwhich is supposed to handle this case, but it's not being hit when the shell opens the file, which I don't understand.
I tracked that down step-by-step on Saturday: If the O_TRUNC flag is set in the open() syscall the file will first be truncated and then opened.
The call stack for truncating the file:
- sys_open (fs/open.c)
- do_sys_open (fs/open.c)
- do_filp_open (fs/open.c)
- open_namei (fs/namei.c)
- may_open (fs/namei.c)
- do_truncate (fs/open.c)
And the call stack for actually opening the file:
- sys_open (fs/open.c)
- do_sys_open (fs/open.c)
- do_filp_open (fs/open.c)
- nameidata_to_filp (fs/open.c)
- __dentry_open (fs/open.c)
Maybe that helps.
Quoted 4 lines
Correct. I've pondered using [id]notify to track changes on the host and either invalidate the UML cache or update it. Both involve interactions with the page cache that I'm not entirely comfortable with right now.
That problem is actually more severe for my UML use case: I'm developing firmware for an embedded device, and I'm using UML because it's quicker and more convenient than developing on the target hardware. Now, if I re-compile some library which is still in use by another process the changes will not be visible until I reboot (or kill these background processes).
How do similar filesystems (e.g. NFS) solve that problem?
Cheers,
Ingo
-------------------------------------------------------------------------
Sponsored by: SourceForge.net Community Choice Awards: VOTE NOW! Studies have shown that voting for your favorite open source project, along with a healthy diet, reduces your potential for chronic lameness and boredom. Vote Now at http://www.sourceforge.net/community/cca08
_______________________________________________
User-mode-linux-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel
Quoted 11 lines · Ingo van Lil
The call stack for truncating the file:
-
sys_open(fs/open.c)
-do_sys_open(fs/open.c)
-do_filp_open(fs/open.c)
-open_namei(fs/namei.c)
-may_open(fs/namei.c)
-do_truncate(fs/open.c)And the call stack for actually opening the file:
Quoted 7 lines
-
sys_open(fs/open.c)
-do_sys_open(fs/open.c)
-do_filp_open(fs/open.c)
-nameidata_to_filp(fs/open.c)
-__dentry_open(fs/open.c)Maybe that helps.
Yeah, I was suspecting that something was causing operations on the file before hostfs was asked to actually open it. Hmm.
Jeff
Signature · 11 lines
Work email - jdike at linux dot intel dot com ------------------------------------------------------------------------- Sponsored by: SourceForge.net Community Choice Awards: VOTE NOW! Studies have shown that voting for your favorite open source project, along with a healthy diet, reduces your potential for chronic lameness and boredom. Vote Now at http://www.sourceforge.net/community/cca08 _______________________________________________ User-mode-linux-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel
Quoted 9 lines · Jeff Dike
Quoted 4 lines
I guess this is some kind of caching effect, because strace shows that there is only a single read to the actual physical file. Maybe hostfs should check whether the outside file has changed and invalidate the cache if necessary.
Correct. I've pondered using [id]notify to track changes on the host and either invalidate the UML cache or update it. Both involve interactions with the page cache that I'm not entirely comfortable with right now.
I gave all this a little more thought: The ideal solution would be to somehow share the host's page cache for that file. That way concurrent read and write accesses on both sides would be automatically synchronized, just as when multiple regular processes access the same file. I guess that's not easily possible, is it?
If it turns out we have to invalidate the cache whenever the file is changed on the host side it looks like invalidate_inode_pages2() is the function to use: If I modify the aio_read in hostfs_kern.c to call this function on iocb->ki_filp->f_mapping before every read changes made on the host become immediately visible on the guest. This is also what nfs seems to do.
Regards,
Ingo
-------------------------------------------------------------------------
Sponsored by: SourceForge.net Community Choice Awards: VOTE NOW! Studies have shown that voting for your favorite open source project, along with a healthy diet, reduces your potential for chronic lameness and boredom. Vote Now at http://www.sourceforge.net/community/cca08
_______________________________________________
User-mode-linux-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel
Quoted 5 lines · Ingo van Lil
I gave all this a little more thought: The ideal solution would be to somehow share the host's page cache for that file. That way concurrent read and write accesses on both sides would be automatically synchronized, just as when multiple regular processes access the same file. I guess that's not easily possible, is it?
It is possible. mappng pages from the host into the UML page cache will do that. Adding mmap support to UML is possible, just there hasn't been a lot of demand for it.
Jeff
Signature · 11 lines
Work email - jdike at linux dot intel dot com ------------------------------------------------------------------------- Sponsored by: SourceForge.net Community Choice Awards: VOTE NOW! Studies have shown that voting for your favorite open source project, along with a healthy diet, reduces your potential for chronic lameness and boredom. Vote Now at http://www.sourceforge.net/community/cca08 _______________________________________________ User-mode-linux-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel