symlink.c 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (C) 2017-2023 Oracle. All Rights Reserved.
  4. * Author: Darrick J. Wong <djwong@kernel.org>
  5. */
  6. #include "xfs.h"
  7. #include "xfs_fs.h"
  8. #include "xfs_shared.h"
  9. #include "xfs_format.h"
  10. #include "xfs_trans_resv.h"
  11. #include "xfs_mount.h"
  12. #include "xfs_log_format.h"
  13. #include "xfs_trans.h"
  14. #include "xfs_inode.h"
  15. #include "xfs_symlink.h"
  16. #include "xfs_health.h"
  17. #include "xfs_symlink_remote.h"
  18. #include "scrub/scrub.h"
  19. #include "scrub/common.h"
  20. #include "scrub/health.h"
  21. #include "scrub/repair.h"
  22. /* Set us up to scrub a symbolic link. */
  23. int
  24. xchk_setup_symlink(
  25. struct xfs_scrub *sc)
  26. {
  27. unsigned int resblks = 0;
  28. int error;
  29. /* Allocate the buffer without the inode lock held. */
  30. sc->buf = kvzalloc(XFS_SYMLINK_MAXLEN + 1, XCHK_GFP_FLAGS);
  31. if (!sc->buf)
  32. return -ENOMEM;
  33. if (xchk_could_repair(sc)) {
  34. error = xrep_setup_symlink(sc, &resblks);
  35. if (error)
  36. return error;
  37. }
  38. return xchk_setup_inode_contents(sc, resblks);
  39. }
  40. /* Symbolic links. */
  41. int
  42. xchk_symlink(
  43. struct xfs_scrub *sc)
  44. {
  45. struct xfs_inode *ip = sc->ip;
  46. struct xfs_ifork *ifp;
  47. loff_t len;
  48. int error = 0;
  49. if (!S_ISLNK(VFS_I(ip)->i_mode))
  50. return -ENOENT;
  51. if (xchk_file_looks_zapped(sc, XFS_SICK_INO_SYMLINK_ZAPPED)) {
  52. xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
  53. return 0;
  54. }
  55. ifp = xfs_ifork_ptr(ip, XFS_DATA_FORK);
  56. len = ip->i_disk_size;
  57. /* Plausible size? */
  58. if (len > XFS_SYMLINK_MAXLEN || len <= 0) {
  59. xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
  60. return 0;
  61. }
  62. /* Inline symlink? */
  63. if (ifp->if_format == XFS_DINODE_FMT_LOCAL) {
  64. if (len > xfs_inode_data_fork_size(ip) ||
  65. len > strnlen(ifp->if_data, xfs_inode_data_fork_size(ip)))
  66. xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
  67. return 0;
  68. }
  69. /* Remote symlink; must read the contents. */
  70. error = xfs_symlink_remote_read(sc->ip, sc->buf);
  71. if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, 0, &error))
  72. return error;
  73. if (strnlen(sc->buf, XFS_SYMLINK_MAXLEN) < len)
  74. xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
  75. /* If a remote symlink is clean, it is clearly not zapped. */
  76. xchk_mark_healthy_if_clean(sc, XFS_SICK_INO_SYMLINK_ZAPPED);
  77. return 0;
  78. }