Operating Systems 2014F: Assignment 6
Please submit the answers to the following questions via CULearn by midnight on Wednesday, November 12, 2014. There 20 points in 14 questions.
Submit your answers as a single text file named "<username>-comp3000-assign6.txt" (where username is your MyCarletonOne username). The first four lines of this file should be "COMP 3000 Assignment 6", 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.
Part A
- [1] dd if=/dev/zero of=foo bs=8192 count=32K What is the logical size of the file? How much space does it consume on disk? (Hint: Look at the size option to ls.)
- [1] Run mkfs.ext4 foo. (Say "yes" to operating on a regular file.) Does foo consume any more space?
- [1] What command do you run to check the filesystem in foo for errors?
- [1] Run mount foo /mnt. How does this command change what files are accessible?
- [1] Run df. What device is mounted on /mnt? What is this device?
- [1] Run rsync -a -v /etc /mnt. What does this command do? Explain the arguments as well.
- [1] Run umount /mnt. What files can you still access, and what have gone away?
- [1] Run dd if=/dev/zero of=foo conv=notrunc count=10 bs=512. How does the "conv=notrunc" change dd's behavior (versus the command in question 1)?
- [1] Run sudo mount foo /mnt. What error do you get?
- [1] What command can you run to make foo mountable again? What characteristic of the file system enables this command to work?
- [1] Run the command truncate -s 1G bar. What is the logical size of bar, and how much space does it consume on disk? How does this compare with foo?
- [1] How does the logical size of bar change when you create an ext4 filesystem in it? What about the space consumed on disk?
Part B
- [4] Write your own version of the command line program stat, which simply calls the stat() system call on a given file or directory. Print out file size, number of blocks allocated, reference (link) count, and so forth. What is the link count of a directory, as the number of entries in the directory changes? Useful interfaces: stat()
- [4] Write a program that prints out the last few lines of a file. The program should be efficient, in that it seeks to near the end of the file, reads in a block of data, and then goes backwards until it finds the requested number of lines; at this point, it should print out those lines from beginning to the end of the file. To invoke the program, one should type: mytail -n file, where n is the number of lines at the end of the file to print. Useful interfaces: stat(), lseek(), open(), read(), close().
Solutions
Solutions for this assignment were discussed in Lecture 22.
- Logical size is 268435456 bytes (as reported by ls -l). Physical size is 262144 blocks (as reported by ls -ls). By default ls assumes blocks are 1K in size; thus the physical space taken up by the file is 262144 * 1024 = 268439552 bytes. In other words, the physical size is 4096 bytes larger than the logical size. Note ext4 by default uses 4K blocks.
- No - it consumes less space. The logical size stays the same, but now it only consumes 8798208 bytes. In other words the physical size is around 3.3% of the logical size! (Note mkfs.ext4 somehow inserted "holes" into the file.)
- fsck.ext4. Just using the fsck command alone on a regular file like foo (in this environment) will only display the usage options.
- Anything previously in /mnt is now not available, and the files of the filesystem in foo are now available within /mnt.
- /dev/loop0. This is a loop block device. It allows a file such as foo (associated with the device) to be accessed as if it were a block device. (NOTE: In class we referred to this as the "loopback block" device, but to reduce confusion it is normally referred to as the loop device.)
- The command "rsync -a -v /etc /mnt" synchronizes the contents of /etc to /mnt. Specifically it only copies the files from the source (/etc) to the destination (/mnt) if they need to be; files that are already the same in both locations are not touched. The -a option means archive (use recursion and grab almost everything and preserve as much file metadata as possible). The -v option says to be verbose; without it rsync runs quietly (unless it encounters an error). Note that with these options files that exist in the destination but not in the source are preserved. If you want extraneous files and directories to be deleted in the destination, add "--delete --force".
- Any files that were previously in /mnt before the mount command are now accessible. Any files that were in /mnt (i.e, in the foo filesystem) are no longer accessible.
- conv=notrunc means that dd will not truncate the file after it is done writing; it leaves the rest of the file intact.
- error is: mount: you must specify the filesystem type
- fsck.ext4 foo (on some versions of fsck you may have to manually specify the location of a backup superblock)
- Logical size is 1G. Physical size is 0. In contrast, physical size (when initially created) was just a bit larger than the logical size.
- The logical size stays the same. The physical size increases (to 33,968,128 bytes).
- Two parts:
- Every subdirectory added The command "man 2 stat" describes the stat API. For a full version of a C program parsing what stat returns (and a bit more) see: http://git.savannah.gnu.org/cgit/coreutils.git/tree/src/stat.c
- A directory has a link count that starts at 2: one is the normal one coming from the entry in the parent directory, while the second comes from the "." entry (the directory links to itself). Every subdirectory added increases the link count by one, because of the .. entry in each subdirectory.
- You need to create a program that reads a chunk of the file from the end of the file, counts the lines in it, and then repeats until it finds the position of the start of the number of lines to be output. It then should read and output the lines from that position in the file (potentially using previously read data or reading it again). See the file_lines() function in the GNU coreutils tail implementation: http://git.savannah.gnu.org/cgit/coreutils.git/tree/src/tail.c#n481 Note that the rest of this implementation of tail handle things like reading from a pipe and reading the last lines of a file forever (the -f option).