Repository navigation
Moves inside a DFS link fail across folders, and bulk copies pay a refused request per file #21
Copy link
Copy link
Open
Labels
Description
Context
Since #15, every path-taking SmbClient call follows a DFS link inside a share. The flow per call: send the CREATE, get STATUS_PATH_NOT_COVERED, look up the referral (from the cache after the first time), and run the op again on the target.
Problem
Two gaps remain:
- Renames across directories through a link fail.
rename/rename_filesmove the destination along only when source and destination sit in one directory. Otherwise they returnSTATUS_PATH_NOT_COVERED. A move fromdata/a/x.txttodata/b/x.txt, withdataa link, fails on a share where a plain move would work. - Every linked item pays a refused CREATE. Batch and streaming calls send one CREATE per item that the server refuses before the redirect, even when the referral cache already knows the path is behind a link. A 1,000-file copy out of a link costs 1,000 extra round trips (about 1–10 s on a LAN, far more over a VPN).
Solution
- Rename: pass the referral's consumed prefix through to the op, so the destination can be rewritten the same way as the source whenever both sit under the same link, and keep
STATUS_PATH_NOT_COVEREDonly when they don't (a cross-link move, which SMB can't do in one call anyway). - Pre-check: before sending, look the path up in the referral cache (MS-DFSC § 3.1.4.1 describes this client-side check), and go straight to the target when it hits. Keep the refused-CREATE path as the fallback for a cold cache or an expired entry.
For the implementer
SmbClient::follow_dfs_link,redirect, andlink_rename_targetincrates/smb2/src/client/mod.rs;DfsResolverinclient/dfs.rs; the link-tree cache inclient/connections.rs(link_tree).- Tests: a mock test that a cached link sends no refused CREATE; a Docker test on
smb-dfs-rootfor a cross-directory rename under the link. - Watch the TTL: a cached referral past its TTL must fall back to the refused-CREATE path, not reuse the stale target (see the TTL refresh issue, Refresh DFS referrals in the background before they expire #16).
After #20
- Rename:
redirectnow returns aLinkcarrying the referral depth and the target folder offset, which is what a cross-directory rename needs. What's missing is getting it into the op before it sends (the op only sees(conn, tree, remaining)): pass theLinkin, or split rename into a redirect step and the SET_INFO.link_rename_targetcan then go. - Pre-check: since the caller's tree no longer moves, every repeat call through a link pays the refused CREATE, single-file calls included, so the pre-check is worth a bit more. It can reuse
redirectandLinkas they are.
Impact: Moves inside a DFS link work, and bulk copies out of a link skip one round trip per file · Severity: Low (moves fail with a clear error, and the extra round trips only cost speed) · Size: M (plumbing a prefix through, plus a cache pre-check)
Found while implementing #15.
Reactions are currently unavailable
Activity