diff --git a/internal/archiver/archiver.go b/internal/archiver/archiver.go index 77ddba7c4..63a1691b3 100644 --- a/internal/archiver/archiver.go +++ b/internal/archiver/archiver.go @@ -188,6 +188,12 @@ func (arch *Archiver) nodeFromFileInfo(snPath, filename string, fi os.FileInfo) if !arch.WithAtime { node.AccessTime = node.ModTime } + if node.Links == 1 || node.Type == "dir" { + // the DeviceID is only necessary for hardlinked files + // when using subvolumes or snapshots their deviceIDs tend to change which causes + // restic to upload new tree blobs + node.DeviceID = 0 + } // overwrite name to match that within the snapshot node.Name = path.Base(snPath) if err != nil { diff --git a/internal/archiver/archiver_test.go b/internal/archiver/archiver_test.go index 46ef44251..3d50e555f 100644 --- a/internal/archiver/archiver_test.go +++ b/internal/archiver/archiver_test.go @@ -2153,6 +2153,7 @@ func TestMetadataChanged(t *testing.T) { sn, node2 := snapshot(t, repo, fs, nil, "testfile") // set some values so we can then compare the nodes + want.DeviceID = 0 want.Content = node2.Content want.Path = "" if len(want.ExtendedAttributes) == 0 { diff --git a/internal/restic/node.go b/internal/restic/node.go index cbe9ef363..e7688aada 100644 --- a/internal/restic/node.go +++ b/internal/restic/node.go @@ -82,7 +82,7 @@ type Node struct { User string `json:"user,omitempty"` Group string `json:"group,omitempty"` Inode uint64 `json:"inode,omitempty"` - DeviceID uint64 `json:"device_id,omitempty"` // device id of the file, stat.st_dev + DeviceID uint64 `json:"device_id,omitempty"` // device id of the file, stat.st_dev, only stored for hardlinks Size uint64 `json:"size,omitempty"` Links uint64 `json:"links,omitempty"` LinkTarget string `json:"linktarget,omitempty"`