google / crfs

CRFS: Container Registry Filesystem

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Support merging layers using Overlayfs

ktock opened this issue · comments

Enabling to merge CRFS layers using overlayfs is valuable (I know currently fuse-overlayfs trying to support CRFS).

But currently CRFS has a cache related issue to achive it.

Issue Reproduction

On terminal A, run crfs:

# ./crfs -fuse_debug

On terminal B, mount crfs as overlayfs and access on it every second:

# mkdir merged upper work
# CRFS_PATH=/crfs/layers/gcr.io/reasonablek8s/ubuntu/18.04 ; mount -t overlay overlay -o lowerdir=${CRFS_PATH}/3:${CRFS_PATH}/2:${CRFS_PATH}/1:${CRFS_PATH}/0,upperdir=upper,workdir=work merged
# for i in $(seq 0 100) ; do echo -n "${i}: " && ls $(pwd)/merged/lib ; sleep 1 ; done

Then, on terminal B, we see ESTALE after 1 min:

0: init  lsb  systemd  terminfo  udev  x86_64-linux-gnu
1: init  lsb  systemd  terminfo  udev  x86_64-linux-gnu
2: init  lsb  systemd  terminfo  udev  x86_64-linux-gnu
...
60: ls: cannot access '/home/kohei/local/experiment/lazypull/crfs/merged/lib': Stale file handle
61: ls: cannot access '/home/kohei/local/experiment/lazypull/crfs/merged/lib': Stale file handle
63: ls: cannot access '/home/kohei/local/experiment/lazypull/crfs/merged/lib': Stale file handle

On terminal A, kernel seems not to be satisfied with inode returned by "Lookup".

2019/09/12 12:17:05 fuse debug: <- Lookup [ID=0x31f Node=0x9 Uid=0 Gid=0 Pid=27867] "lib"
2019/09/12 12:17:05 fuse debug: -> [ID=0x31f] Lookup 0x11 gen=4 valid=1m0s attr={valid=720h0m0s ino=824640017696 size=0 mode=drwxr-xr-x}
2019/09/12 12:17:05 fuse debug: <- Forget [ID=0x320 Node=0x11 Uid=0 Gid=0 Pid=0] 1
2019/09/12 12:17:05 fuse debug: -> [ID=0x320] Forget

The cause of issue

CRFS generates different "Node" instance everytime "Lookup" is called. This behavior makes bazil/fuse assign different "Node IDs"(used by FUSE) to inodes everytime even if these "Lookups" point to same file because bazil/fuse caches "Node IDs" keyed by a "Node" insatance (not an inode number etc.). Most time (when we don't use overlayfs etc.) it is fine.

However, when dentry cache revalidation is executed and the dentry is expired (by default, set to 1 min in bazil/fuse.), FUSE "lookups" the original inode and it doesn't allow different Node IDs to same inode and concludes the cache as invalid. Unfortunately, overlayfs doesn't allow dentry caches being invalid and returns ESTALE.

As a result, CRFS currently doesn't support to merge the layers with overlayfs.

Solution

Cache "node" instances in CRFS once it lookedup, and use it when the same name is looked up.
I'll submit the patch as PR.