Sale!

CSC369 Tut7: FUSE Passthrough Solved

$35.00

Category:

Description

5/5 - (1 vote)

Introduction

The purpose of this tutorial is to gain some familiarity with FUSE before you start working on your A5 file
system implementation. FUSE allows you to implement a file system in user space by implementing the
callback functions that the libfuse library will call.
The starter code for the tutorial is a very simple “pass through” file system. Running passthrough will
mount a file system at the directory you specify, and then every operation you perform on files and
directories in that mount point will be passed through to the real file system. Your task is simply to add
one print statement to each of the FUSE callback functions, and see which file system operations trigger
which callbacks.

Your programming task is very simple. It will take longer to read this document and run the program
initially than to write the code.
Here is a short video (https://web.microsoftstream.com/video/562b6a38-bb31-41d5-bb0d-6367301c4f44)
from Winter 2021 that explains some of the code and shows how to run it. Don’t be alarmed by
references to Tut3 or A1, as the file system assignment was placed at the start of the term in that year.

Step 1: Using FUSE

There are two recommended ways to work with FUSE for the tutorial (and the assignment). Both of them
will require some facility with the command-line file system operations. To be able to use FUSE, it must
be running in your kernel, so this means that it is not feasible to run the code for this tutorial on your Mac
OS, Windows, or WSL on Windows. These operating systems have FUSE installed, but they have not
turned on the options that allow you to implement your own file system.
A. Using csc369.teach.cs.toronto.edu
Our system administrators have set up a server just for CSC369 with FUSE installed. To log into this
server, you must first log into teach.cs.toronto.edu , and from there ssh
into csc369.teach.cs.toronto.edu .
For example, from a terminal on my machine, I run:

Then in that terminal, run
ssh csc369.teach.cs.toronto.edu
to log into the csc369 server. You still have access to all of your files on the teach.cs machines, so you
can clone your repository for this exercise.
B. Using a VM on your own machine
You can run FUSE using an Ubuntu virtual machine. Here are our recommendations for the setup:
VirtualBox (https://www.virtualbox.org/) is a free open-source hypervisor that allows you to run a
guest OS on top of your machine. It is pretty easy to install.
Now install Ubuntu 18.04 as a VM in VirtualBox. I used an image from osboxes.org
(https://www.osboxes.org/ubuntu/) , but you may find others. You can find tutorials
(https://www.wikihow.com/Install-Ubuntu-on-VirtualBox) that explain the process. NOTE: your VM
must be 64-bit.
Make sure your FUSE version is 2.9.* (run fusermount –version ).
Install additional packages:
sudo apt-get install libfuse-dev pkg-config
To attach gdb to a running process you will need to change a security setting on Linux. You can do
that using the following commands:
sudo bash
echo 0 > /proc/sys/kernel/yama/ptrace_scope
You may want to increase the screen resolution for the VM. You can do this by selecting the “Show
Applications” button in the bottom left corner and then going to Settings->Devices->Displays and
changing the resolution.

Getting Started

It is very important to follow these instructions and to read carefully. It is possible to delete files you didn’t
intend to if you aren’t careful.
First, set up your repository.
Log into MarkUs first, click on ‘T7’ and then click the ‘Add Starter Files to Repository’ button on
the lower left to set up your git repo for this tutorial.
Use ‘git pull’ to update an existing clone of your MarkUs repo, or ‘git clone’ to create a fresh copy
of the repository.
Build the passthrough program by running make in your T7 directory.
Create a directory in your account called rootdir . You can create rootdir in the same directory that
contains your starter code, but you should NOT commit it to your repository. You can also create it
elsewhere in your account.

Log in (via ssh from another teach.cs server) to the csc369.teach.cs.toronto.edu server and create a
directory /tmp/USERID where USERID is replaced with your user id. This will be the directory where
you mount the pass-through file system. You need to create this mount point in /tmp (on the
csc369.teach.cs.toronto.edu server) because the fuse library code that handles the FUSE unmount
command doesn’t have permissions on your home directory. Mounting a fuse file system to a location
where fuse can’t unmount it can leave you with directories that you can’t remove and can’t use.
Important: The /tmp directory is local to each server, unlike your home directory which is available on
all the teach.cs servers. Make sure that you have created /tmp/USERID on csc369.teach.cs, and not
on another server like wolf or hippo.

The rootdir will be the root directory ( / ) of the pass-through file system. Anything you add to
the rootdir directory will be visible to the pass-through file system.
The /tmp/USERID directory is where the pass-through file system will be mounted. After starting the
passthrough program, any file system operations performed in the /tmp/USERID directory or its subdirectories will be calling the FUSE code. Any files or directories created under /tmp/USERID will be
visible under rootdir as well.

The passthrough program takes 3 arguments that we care about:

-f or -d options. The -f option keeps the connection to the terminal so that
when passthrough writes to stdout or stderr it will appear on the terminal. The -d option keeps the
connection to the terminal and prints lots of debugging information. You should be running the
program with one of these two options. Without either -f or -d, libfuse detaches from the terminal and
runs in the background. You will not be able to see any output from either libfuse or the passthrough
file system.

The second argument is the path to rootdir (see above for explanation of this directory)
The third argument is the path to /tmp/USERID . This must be an empty directory that you have
created and have permissions on. It should NOT be a sub-directory of the directory that you passed
in as the second argument above.
Suggested approach: Open two terminal windows on the csc369.teach.cs server. In the first terminal
window you will set up and run passthrough as described in the above paragraphs. In the second you
will run file system operations in /tmp/USERID .
Example:
# First terminal
> ls
Makefile passthrough.c
> make
gcc passthrough.c -o passthrough.o -c -MMD -D_FILE_OFFSET_BITS=64 -I/usr/include/fuse -g3 -Wall -Wex
tra -Werror
gcc passthrough.o -o passthrough -lfuse -pthread
> mkdir ./rootdir
> mkdir /tmp/USERID
> ls
Makefile passthrough* passthrough.c passthrough.d passthrough.o rootdir/

> touch rootdir/afile
> mkdir rootdir/dir1
> ./passthrough -d ./rootdir /tmp/USERID
FUSE library version: 2.9.9
nullpath_ok: 0
nopath: 0
utime_omit_ok: 0
unique: 2, opcode: INIT (26), nodeid: 0, insize: 56, pid: 0
INIT: 7.34
flags=0x33fffffb
max_readahead=0x00020000
INIT: 7.19
flags=0x00000011
max_readahead=0x00020000
max_write=0x00020000
max_background=0
congestion_threshold=0
unique: 2, success, outsize: 40
The output from these commands continues.

The passthrough program will run until you kill it, and every time you do an operation on files or
directories under /tmp/USERID , you should see more output. Eventually, you will understand more of
what the output means, but for now, focus on the fact that FUSE is doing some work.
Now in the second terminal window, perform some file system operations on the directory /tmp/USERID
– create some files, make some directories, read and write to files, etc. For example, try these
operations: (Remember to replace USERID with your own user id.)
> ls /tmp/USERID
> touch /tmp/USERID/afile
> echo “a new file” > /tmp/USERID/bfile
> cd /tmp/USERID
> echo “some text” > afile
> cat afile
> cat bfile
> mkdir dir2
> mv bfile dir2

I’m sure you can think of more things to try. (Note: If you follow the above commands exactly, and you
have “noclobber” set in your .bashrc file, you will see “cannot overwrite existing file” when redirecting
output to the existing “afile”. This is because of your shell settings, not because of FUSE. For bash, try
“>|” to redirect output and override the noclobber, e.g. echo “some text” >| afile )
When you kill the passthrough program, it should unmount the file system. However,
if passthrough terminates abnormally (segfault for example), then it may not properly unmount the file
system. In that case you can use the command fusermount -u /tmp/USERID .
Try listing /tmp/USERID after killing the passthrough program. Now that the pass-through file system is
no longer mounted there, you should see only an empty directory. The files and directories you created
or modified under /tmp/USERID continue to be visible at rootdir/ .

Your Task

You will add one print statement to each of the functions mentioned in the passthrough_ops struct. These
are the functions that will be called by the FUSE library.
The print statements for passthrough_getattr and passthrough_readdir are shown below. The other print
statements must follow the same pattern.
fprintf(stderr, “getattr(%s, %p)\n”, path, (void *)st);
fprintf(stderr, “readdir(%s, %p, %ld)\n”, path, buf, offset);
Notes:
Print to stderr.
Print the name of the function without passthrough_ .
Print the parentheses, and put a comma between each argument.
Print the arguments in the order that they appear in the function parameter list.
Ignore parameters of type fuse_fill_dir_t and struct fuse_file_info
If an argument is of type char * , then print the string unless the argument is a buffer (e.g., char
*buf in passthrough_read ). For buffer arguments, print the address of the buffer (see readdir
example).

If an argument is a pointer to a struct, print the address (see getattr example).
If an argument is a number then print the number. The type off_t uses the format
” %ld” (see readdir example); the type size_t is unsigned and uses the format ” %lu” .
If an argument is of type mode_t use the format ” %04o ” (modes are traditionally displayed in octal).
Ensure there is a newline at the end of the print statement.

What to submit

Commit your modified passthrough.c file to your repository, first making sure that it compiles cleanly
without warnings. You must also answer the questions in the Quercus quiz linked below.
Answer the questions in the quiz. To get full marks, you must get all the answers correct, but you can
submit the quiz multiple times, and the last submission counts. Remember that the purpose of this
tutorial is to help you get started with the assignment, so it is worthwhile to make sure you understand
what is happening.
Take the Quiz