Add sync hardlink preserve support for local->NFS#3383
Open
dphulkar-msft wants to merge 77 commits intodphulkar/NFSOverRESTSupportfrom
Open
Add sync hardlink preserve support for local->NFS#3383dphulkar-msft wants to merge 77 commits intodphulkar/NFSOverRESTSupportfrom
dphulkar-msft wants to merge 77 commits intodphulkar/NFSOverRESTSupportfrom
Conversation
…Azure/azure-storage-azcopy into dphulkar/hardlinkDesignPOC
…e/azure-storage-azcopy into dphulkar/hardlinkDesignPOC
…e/azure-storage-azcopy into dphulkar/hardlinkDesignPOC
…/azure-storage-azcopy into dphulkar/hardlinkNFSToLocal
…e/azure-storage-azcopy into dphulkar/hardlinkNFSToLocal
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…e-storage-azcopy into dphulkar/hardlinkSync
Contributor
There was a problem hiding this comment.
Pull request overview
Adds hardlink preservation support for sync/copy Local → Azure Files NFS, introducing inode-based hardlink grouping so sync can detect/maintain hardlink relationships (including group merges/splits and anchor changes).
Changes:
- Introduces an on-disk, per-job
InodeStoreand plumbs it through traversers and sync/copy execution paths. - Extends
StoredObjectwithInodeand refactors NFS hardlink metadata handling viaNFSMetadataContext. - Updates sync comparator to defer destination hardlink processing and reconcile hardlink group structure; adds substantial unit/e2e coverage.
Reviewed changes
Copilot reviewed 33 out of 34 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| traverser/zc_traverser_s3.go | Updates NewStoredObject call signature for NFS metadata context. |
| traverser/zc_traverser_local.go | Adds inode store plumbing and emits inode/hardlink context during local enumeration. |
| traverser/zc_traverser_gcp.go | Updates NewStoredObject call signature for NFS metadata context. |
| traverser/zc_traverser_file.go | Adds inode store usage for Azure Files hardlink grouping and passes inode context into StoredObject. |
| traverser/zc_traverser_blob_versions.go | Updates NewStoredObject call signature for NFS metadata context. |
| traverser/zc_traverser_blob.go | Updates NewStoredObject call signature for NFS metadata context across blob enumeration paths. |
| traverser/zc_traverser_benchmark.go | Updates benchmark traverser to new NewStoredObject signature. |
| traverser/zc_enumerator.go | Adds Inode to StoredObject, introduces NFSMetadataContext, updates NewStoredObject signature, extends traverser init options with InodeStore. |
| ste/xfer-remoteToLocal-hardlink.go | Adjusts hardlink download flow for updated downloader interface and prologue usage. |
| ste/xfer-anyToRemote-hardlink_test.go | Adds unit tests for upload hardlink target path computation. |
| ste/xfer-anyToRemote-hardlink.go | Computes upload hardlink target path based on source-root-relative suffix and uses it for CreateHardlink. |
| ste/testJobPartTransferManager_test.go | Extends test JPTM to satisfy new GetSourceRoot() interface method. |
| ste/mgr-JobPartTransferMgr.go | Adds GetSourceRoot() to JPTM interface and implementation (sourced from plan). |
| ste/mgr-JobMgr.go | Ensures queued hardlink-only parts can be dispatched even when no mixed parts complete. |
| ste/downloader.go | Updates hardlink downloader interface signature. |
| ste/downloader-blobFS.go | Removes stale/incorrect hardlink stub method. |
| ste/downloader-azureFiles_linux_test.go | Adds unit tests for download hardlink target path computation on Linux. |
| ste/downloader-azureFiles_linux.go | Implements local hardlink creation using computed anchor target path; adds computeDownloadHardlinkTarget. |
| e2etest/zt_newe2e_nfs_scenarios_test.go | Improves NFS cleanup behavior and adjusts scenario logic for sync/hardlink preserve. |
| e2etest/zt_newe2e_nfs_hardlink_sync_test.go | Adds extensive e2e coverage for hardlink-preserve sync/copy scenarios. |
| e2etest/newe2e_task_validation.go | Adjusts validation to avoid content validation for preserved hardlinks. |
| common/inodeStore_test.go | Adds comprehensive unit test suite for new inode store behavior (rehydration, concurrency, edge cases). |
| common/inodeStore.go | Replaces singleton inode store with per-job on-disk indexed store supporting anchor tracking and resume rehydration. |
| cmd/zt_sync_file_file_test.go | Updates sync comparator construction for new comparator signature. |
| cmd/zt_generic_processor_test.go | Updates NewStoredObject call to new NFS options signature. |
| cmd/removeEnumerator.go | Updates remove enumerator to new NewStoredObject signature. |
| azcopy/syncProcessor.go | Treats hardlinks similarly to files in deletion logging behavior. |
| azcopy/syncOptions.go | Removes prior validation blocking --hardlinks=preserve for sync. |
| azcopy/syncEnumerator.go | Plumbs inode store into traversers; adds pending-hardlink post-processing in sync finalize. |
| azcopy/syncComparator.go | Adds hardlink-aware sync comparison, including deferred processing and group structure reconciliation. |
| azcopy/sync.go | Creates per-job inode store for sync execution and passes it through syncer. |
| azcopy/output.go | Adds “Hardlinks Transferred” to sync job summary output. |
| azcopy/copyEnumerator.go | Plumbs inode store into copy enumerator traverser initialization. |
| azcopy/copy.go | Creates per-job inode store for copy execution and passes it through transfer executor. |
Comments suppressed due to low confidence (1)
traverser/zc_enumerator.go:416
InitResourceTraverserOptions.PerformCheckscurrently doesn’t enforce the documented invariant thatInodeStoremust be non-nil whenHardlinkHandling == Preserve. Several traversers now return runtime errors wheninodeStoreis nil; it would be safer to fail fast here with a clear validation error.
func (o *InitResourceTraverserOptions) PerformChecks() error {
if o.IncrementEnumeration == nil {
o.IncrementEnumeration = enumerationCounterFuncNoop
}
return nil
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Contributor
|
@dphulkar-msft I've opened a new pull request, #3411, to work on those changes. Once the pull request is ready, I'll request review from you. |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…e-storage-azcopy into dphulkar/hardlinkSync
adreed-msft
approved these changes
Mar 19, 2026
gapra-msft
reviewed
Mar 20, 2026
gapra-msft
approved these changes
Mar 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Feature / Bug Fix: (Brief description of the feature or issue being addressed)
Related Links:
Issues
Team thread
Documents
[Email Subject]
Type of Change
How Has This Been Tested?
Thank you for your contribution to AzCopy!