Bug #11034

Restoring previous versions from snapshots doesn't work with nested datasets

Added by Gordon Ross 3 months ago. Updated 3 months ago.

In Progress
Start date:
Due date:
% Done:


Estimated time:


Steps to Reproduce:
Using "Previous Versions" tab in Windows, to look at "snapshots" data history.

shares are:

zfs/pool1/data smb=()
zfs/pool1/data/gpsource smb=()
zfs/pool1/data/gpsource/work smb=()

Testfile - path /volumes/pool1/data/gpsource/work/Case-Data/nested-folder-4.txt

1) Modify file "nested-folder-{x}.txt".

2) Take recursive snapshot of dataset "zfs snapshot -r pool1/data@initial"

3) Modify file "nested-folder-{x}.txt"

4) Take recursive snapshot of dataset "zfs snapshot -r pool1/data@initial-1"

5) Open MS Explorer on share and look at folder \\{server}\pool1_data "Previous Version" tab

and you can see 2 snapshots.

6) Looking at folder \\{server}\pool1_data\gpsource\work\Case-Data you do not see any "snapshots".

Expected Results:
You expect to see previous snapshots.

Actual Results:
You don't see any snapshots.



Updated by Gordon Ross 3 months ago

  • Status changed from New to In Progress
  • Description updated (diff)

From Matt Barden

The root cause of the bug here is the combination of the following:
1. "Previous Version" lookups are done in the .zfs/snapshots/<snap name> directory of the filesystem at the root of the share.
2. In these snapshots, mounted filesystems are represented as plain, empty directories, and so mount traversal through snapshots is impossible.

The high-level description of fix for this, barring any changes to ZFS to make mount traversal possible through snapshots (which are unlikely to happen and, even if they did, probably wouldn't be backwards-compatible), is to instead do the lookup in the snapshots directory of the lowest-level filesystem in the path. However, answering the question "What is the lowest-level filesystem in the given path?" is far more complex a problem than it may seem on the surface.

Answering this question requires handling Mangled names, links, case insensitivity, mount traversal, and any of the other Windows-like functionality required. It is not as simple as comparing the requested path to mnttab, like SMBD does, or building and maintaining a Share.SnapshotsList, like Windows does. Additionally, one must consider that parent directories sometimes grant implicit permissions on their children, and Windows Explorer allows users to browse previous versions of filesystems directly, meaning that the current directory layout may not mirror the snapshot. All of these combine to make this a more difficult problem than it first appears.

With some compromises, we can implement a fix for this, by first looking up the file outside of VSS and then, success or ENOENT, replaying the last bit of the lookup on the lowest discovered mountpoint. The following compromises are required:
1. Mountpoints cannot be renamed. If the location of the filesystem in the hierarchy changes, we can no longer discover the lowest existing filesystem in the path. Directories below the mountpoint can be changed. This compromise is virtually impossible to avoid.
2. Implicit permissions granted by parent directories may be incorrect. Only two such permissions are currently known: DELETE and READ_ATTRIBUTES. Because Previous Versions are read-only, we don't need to worry about delete. Hopefully the snapshot root directory grants LIST_DIRECTORY - I don't see how it couldn't - or else that particular permissions inheritance won't work. Customers should generally be explicitly granting permissions on objects anyway, rather than relying on parent permissions to grant them implicitly.
3. Previous Version performance might suffer. We can't really avoid doing multiple lookups in this path. It's still better than not working at all.

Also available in: Atom PDF