You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

59 lines
2.9 KiB

  1. # rename and link
  2. **NOTE:** If you're receiving errors from software when files are
  3. moved / renamed / linked then you should consider changing the create
  4. policy to one which is **not** path preserving, enabling
  5. `ignorepponrename`, or contacting the author of the offending software
  6. and requesting that `EXDEV` (cross device / improper link) be properly
  7. handled.
  8. `rename` and `link` are arguably the most complicated functions to
  9. create in a union filesystem. `rename` only works within a single
  10. filesystem or device. If a rename can't be done due to the source and
  11. destination paths existing on different mount points it will return
  12. **-1** with **errno = EXDEV** (cross device / improper link). So if a
  13. `rename`'s source and target are on different filesystems within the
  14. pool it creates an issue.
  15. Originally mergerfs would return EXDEV whenever a rename was requested
  16. which was cross directory in any way. This made the code simple and
  17. was technically compliant with POSIX requirements. However, many
  18. applications fail to handle EXDEV at all and treat it as a normal
  19. error or otherwise handle it poorly. Such apps include: gvfsd-fuse
  20. v1.20.3 and prior, Finder / CIFS/SMB client in Apple OSX 10.9+,
  21. NZBGet, Samba's recycling bin feature.
  22. As a result a compromise was made in order to get most software to
  23. work while still obeying mergerfs' policies. Below is the basic logic.
  24. * If using a **create** policy which tries to preserve directory paths (epff,eplfs,eplus,epmfs)
  25. * Using the **rename** policy get the list of files to rename
  26. * For each file attempt rename:
  27. * If failure with ENOENT (no such file or directory) run **create** policy
  28. * If create policy returns the same branch as currently evaluating then clone the path
  29. * Re-attempt rename
  30. * If **any** of the renames succeed the higher level rename is considered a success
  31. * If **no** renames succeed the first error encountered will be returned
  32. * On success:
  33. * Remove the target from all branches with no source file
  34. * Remove the source from all branches which failed to rename
  35. * If using a **create** policy which does **not** try to preserve directory paths
  36. * Using the **rename** policy get the list of files to rename
  37. * Using the **getattr** policy get the target path
  38. * For each file attempt rename:
  39. * If the source branch != target branch:
  40. * Clone target path from target branch to source branch
  41. * Rename
  42. * If **any** of the renames succeed the higher level rename is considered a success
  43. * If **no** renames succeed the first error encountered will be returned
  44. * On success:
  45. * Remove the target from all branches with no source file
  46. * Remove the source from all branches which failed to rename
  47. The removals are subject to normal entitlement checks. If the unlink
  48. fails it will fail silently.
  49. The above behavior will help minimize the likelihood of EXDEV being
  50. returned but it will still be possible.
  51. **link** uses the same strategy but without the removals.