Operating Systems 2014F: Assignment 8

From Soma-notes

Please submit the answers to the following questions via CULearn by just before midnight (11:55 PM) on Thursday, November 27, 2014. There 20 points in 8 questions.

Submit your answers as a single text file named "<username>-comp3000-assign8.txt" (where username is your MyCarletonOne username). The first four lines of this file should be "COMP 3000 Assignment 8", your name, student number, and the date of submission. You may wish to format your answers in Markdown to improve their appearance.

No other formats will be accepted. Submitting in another format will likely result in your assignment not being graded and you receiving no marks for this assignment. In particular do not submit a zip file, MS Word, or OpenOffice file as your answers document!

Don't forget to include what outside resources you used to complete each of your answers, including other students, man pages, and web resources. You do not need to list help from the instructor, TA, or information found in the textbook.

Note the following questions make reference to the code from Tutorial 8, specifically memoryll.pl.

  1. [1] How does FUSE bring microkernel-like concepts into the Linux kernel?
  2. [1] What is a system call that generates a call to Memory's lookup method?
  3. [1] What are the storage limits on Memory's filesystem? Specifically, under what circumstances do you expect it to run out of storage space?
  4. [2] What is the connection between the buffer given to the read system call and buf in Memory's read method? Specifically, how does data move between them?
  5. [3] Who owns the files created in Memory's filesystem? How is this determined? Is this connected to whether the filesystem was run as root?
  6. [4] What do attr, data, parent, and children store (as properties of a Memory object)? Explain what is stored and how it is organized at a high level and using what kind of Python data structures.
  7. [4] What are self, req, inode, and fi used to store when used as arguments to methods of Memory?
  8. [4] Modify Memory so it has a top-level file called "log" that records all of the file operations that are normally printed in the terminal window (all the print commands). Be sure to make it so that operations on log are not logged!

Solutions

Solutions for this assignment were discussed in Lecture 23.

  1. Microkernels are based on the principle that as much of an operating system's functionality as possible should be in userspace (processes) rather than implemented in the kernel (running in supervisor mode on the CPU). Standard Linux filesystems are implemented inside of the kernel, typically as loadable modules. FUSE allows filesystems to be implemented in userspace.
  2. Any system call that makes use of a pathname (whether it be a file or a directory) in the Memory filesystem causes the lookup method to be invoked. Thus the open system call causes a lookup method, but also system calls such as mkdir and stat do as well. (To get full credit you only needed to name one system call.)
  3. Memory's filesystem should only run out of space when the Python process implementing it runs out of space. Thus, the filesystem can grow to the maximum size of a process. This maximum will in practice be determined by how much RAM and swap space a computer has, e.g., if a computer has 4 GB of RAM and 4 GB of swap, the filesystem won't be more than 8 GB (and will likely be a good bit less).
  4. The kernel copies the data from buf (as returned by Memory's read method) to the buffer passed to the read system call by the calling process. The address spaces of Memory and the calling process are completely separate; the kernel transfers data between them.
  5. The files created in the memory filesystem are owned by the user who started the fuse script and can only be accessed by that user. Even root is excluded. If root starts the script, then root owns and has exclusive access to those files. While it is possible to make FUSE-mounted filesystems accessible to other users this is not the default.
  6. These four dictionaries (some of which are dictionaries of dictionaries) collectively store the entire in-memory filesystem. The contents of each inode are distributed amongst these four dictionaries as follows:
    • attr: Attributes of every inode, indexed by inode number.
    • data: Contents of every file inode, indexed by inode number
    • parent: Stores the inode number of the parent directory of every file and directory. Indexed by inode.
    • children: Stores the entries in a directory, indexed by inode (of the directory) and by name. Associates an inode with this pair.
  7. The arguments are as follows:
    • self: Refers to the object itself, which for this code is the Memory object
    • req: The request object which encapsulates the filesystem request originating from another process (and passed on from the kernel). It is used to return data back to the kernel using the various reply_ methods and to allow Memory to find out about the context of the original request (e.g., the user and group of the process making the system call).
    • inode: refers to the inode number of the inode being referenced. This number is used to index into the data structures discussed in the previous question.
    • fi: this is an object that is just passed through (sometimes) to the reply. It isn't directly used in Memory. (Saying this is sufficient to get full credit.) Note this is only passed on for the open reply. It is essentially an extra data structure that can be setup in open and is then passed on to all other functions that use the opened file. Thus, it is a handy place for putting cache information, for example. As is clear from this example, however, it does not need to be used.
  8. One basic strategy for this question is as follows. First create an empty log file by manually creating a file in the init function, following the pattern for opening a new file. Then you add code to every function that logs a message to the console to instead add to the data string of the logfile - but only if the current operation isn't to the log file itself. See code below.