Hi Martin, Firstly a process does not directly initiates a disk read, the kernel does, and the disk blocks read in are not placed into process address space, but placed in some kernel memory first (in pages in page cache), and then relevant portions are copied to user space using copy_to_user() or some of its siblings. Hence, thats the assumption, I think, is not ok. Now, how does this change things: A and B are two threads of _A_ process. A initiates a read and sleeps and B forks and references the buffer to which A tries to read in the data and the physical address backing that virtual address gets changed because of COW established on it at the time of fork(), right? But this does not change anything because of the following reason: read() is completed by calling copy_to_user() multiple times in one system call context. Suppose x% of the data (x may be zero) is copied from kernel to the buffer before the physical address of the buffer is changed due to COW etc. But that old data is copied to the new physical location to which A and B references through the virtual address of the buffer. And when the next byte of data is to be placed by the kernel to the user process, it places it in the *NEW* physical address and not in the old one (copy_to_user() will take care of it as the page tables of A and B got changed by that time reflecting the new mapping.). So both A and B as well, see that the read() has completed correctly. This is my "IMHO", plz. correct me if I am wrong. regards sourav -------------------------------------------------------------------------------- SOURAV SEN MSc(Engg.) CSA IISc BANGALORE URL : www2.csa.iisc.ernet.in/~sourav -------------------------------------------------------------------------------- "Systems research cannot be just science; there must be engineering, design, and art" - Rob Pike On Thu, 11 Oct 2001, Martin Maletinsky wrote: > Hi, > > I more or less understand the Linux memory management system, but I have a very limited understanding of how I/O works. I am interested in understanding, how I/O is > synchronized with the memory managment, in particular I have the following questions: > > (1) When a process wants to read data from an I/O device (e.g. disk) into a buffer in it's address space, (I assume) the pages containing that buffer must be 'locked', i.e. > prevented from being paged out, while the data transfer is going on. As far as I understood from quickly browsing through the 'Managing I/O Devices' chapter in > 'Understanding the Linux Kernel', this is achieved by setting the PG_locked flag in the corresponding page frame descriptor. Is this correct? > > (2) How is I/O synchronized with the copy-on-write mechanism? Imagine the following scenario: > > (i) Two threads A and B share their virtual address space (i.e. the CLONE_VM flag was set when A called clone() to create B). > > (ii) Thread A starts reading data from a hard disk into a buffer BUF which lies within virtual page VP_1 (which at that moment corresponds to the physical page PP_1). In > order to service the read request, the physical page PP_1 is locked (?) and DMA is set up, to transfer data from the harddisk into the correct location within physical page > PP_1. > > (iii) Thread A sleeps until termination of it's read request. > > (iv) Meanwhile thread B calls fork(), which results in write protection of the virtual page VP_1 (in order to enforce a copy on write at a subsequent write access). > > (v) Thread B writes to the virtual page VP_1 (outside the buffer BUF). This results in a page fault, and subsequently in a copy on write (COW) of the virtual page VP_1. As > a consequence of the COW, the content of PP_1 is copied into a new physical page PP_2 and virtual page VP_1 is associated to PP_2 (by modifying the respective page table > entry for thread A and B). > > Note, that the data transfer from disk is still going on and the data is written into the physical page PP_1. > > (vi) The data transfer from disk terminates and thread A wakes up. Thread A would now expect to find the disk data in buffer BUF. However, when it reads the buffer BUF > within virtual page VP_1, it will access the physical page PP_2. Therefore it will not 'see' the data in the buffer BUF that has been transferred after the COW took place > in (v). > > I guess that I made some wrong assumptions in my scenario, since I can hardly imagine, that it is acceptable that thread A's read request is incorrectly handled, because > thread B calls fork(). Please help me understand how the kernel manages to correctly process both calls. > > regards > Martin > > > -- > Supercomputing System AG email: maletinsky@scs.ch > Martin Maletinsky phone: +41 (0)1 445 16 05 > Technoparkstrasse 1 fax: +41 (0)1 445 16 10 > CH-8005 Zurich > > > - > Kernelnewbies: Help each other learn about the Linux kernel. > Archive: http://mail.nl.linux.org/kernelnewbies/ > IRC Channel: irc.openprojects.net / #kernelnewbies > Web Page: http://www.kernelnewbies.org/ > - Kernelnewbies: Help each other learn about the Linux kernel. Archive: http://mail.nl.linux.org/kernelnewbies/ IRC Channel: irc.openprojects.net / #kernelnewbies Web Page: http://www.kernelnewbies.org/