The next part of pager.c is shown in Program 12. The pager_notify_read function seen on line 1 is registered as the read callback for the /dev/pager/notify device. It blocks the read request using the technique we described earlier: it stores the fusd_file_info pointer in that client's state structure, and returns -FUSD_NOREPLY. (Note that the pointer to the client's state structure comes from the private_data field of fusd_file_info, where the open callback stored it.)
pager_notify_complete_read unblocks previously blocked reads. This function first checks to see that there is, in fact, a blocked read (line 19). It then checks to see if a page has arrived that the client hasn't seen yet (line 23). Finally, it updates the client state and unblocks the blocked read by calling fusd_return. Note the second argument to fusd_return is a 0; as we saw in Section 4.3, a 0 return value to a read system call means EOF. (The system call will be unblocked regardless of the return value.)
pager_notify_complete_read is called every time a new page arrives. New pages are processed by pager_input_write (line 34), which is the write callback for /dev/pager/input. After recording the fact that a new page has arrived, it calls pager_notify_complete_read for each client that has an open file descriptor. This will complete the reads of any clients who have not yet seen this new data, and have no effect on clients that don't have outstanding reads.
There is another interesting point to notice about pager_notify_read. On line 12, after it stores the blocked system call's pointer, but before we return -FUSD_NOREPLY, it calls the completion function. This has the effect of returning any data that might already be available back to the caller immediately. If that happens, we will end up calling fusd_return before we return -FUSD_NOREPLY. This probably seems strange, but it's legal. Recall that a callback can call fusd_return() explicitly or return a normal (not -FUSD_NOREPLY) return value, but not both; the order doesn't matter.