xfs_symlink_remote.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. /*
  2. * Copyright (c) 2000-2006 Silicon Graphics, Inc.
  3. * Copyright (c) 2012-2013 Red Hat, Inc.
  4. * All rights reserved.
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License as
  8. * published by the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope that it would be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write the Free Software Foundation,
  17. * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  18. */
  19. #include "xfs.h"
  20. #include "xfs_fs.h"
  21. #include "xfs_format.h"
  22. #include "xfs_log.h"
  23. #include "xfs_trans.h"
  24. #include "xfs_ag.h"
  25. #include "xfs_sb.h"
  26. #include "xfs_mount.h"
  27. #include "xfs_bmap_btree.h"
  28. #include "xfs_inode.h"
  29. #include "xfs_error.h"
  30. #include "xfs_trace.h"
  31. #include "xfs_symlink.h"
  32. #include "xfs_cksum.h"
  33. #include "xfs_buf_item.h"
  34. /*
  35. * Each contiguous block has a header, so it is not just a simple pathlen
  36. * to FSB conversion.
  37. */
  38. int
  39. xfs_symlink_blocks(
  40. struct xfs_mount *mp,
  41. int pathlen)
  42. {
  43. int buflen = XFS_SYMLINK_BUF_SPACE(mp, mp->m_sb.sb_blocksize);
  44. return (pathlen + buflen - 1) / buflen;
  45. }
  46. int
  47. xfs_symlink_hdr_set(
  48. struct xfs_mount *mp,
  49. xfs_ino_t ino,
  50. uint32_t offset,
  51. uint32_t size,
  52. struct xfs_buf *bp)
  53. {
  54. struct xfs_dsymlink_hdr *dsl = bp->b_addr;
  55. if (!xfs_sb_version_hascrc(&mp->m_sb))
  56. return 0;
  57. dsl->sl_magic = cpu_to_be32(XFS_SYMLINK_MAGIC);
  58. dsl->sl_offset = cpu_to_be32(offset);
  59. dsl->sl_bytes = cpu_to_be32(size);
  60. uuid_copy(&dsl->sl_uuid, &mp->m_sb.sb_uuid);
  61. dsl->sl_owner = cpu_to_be64(ino);
  62. dsl->sl_blkno = cpu_to_be64(bp->b_bn);
  63. bp->b_ops = &xfs_symlink_buf_ops;
  64. return sizeof(struct xfs_dsymlink_hdr);
  65. }
  66. /*
  67. * Checking of the symlink header is split into two parts. the verifier does
  68. * CRC, location and bounds checking, the unpacking function checks the path
  69. * parameters and owner.
  70. */
  71. bool
  72. xfs_symlink_hdr_ok(
  73. struct xfs_mount *mp,
  74. xfs_ino_t ino,
  75. uint32_t offset,
  76. uint32_t size,
  77. struct xfs_buf *bp)
  78. {
  79. struct xfs_dsymlink_hdr *dsl = bp->b_addr;
  80. if (offset != be32_to_cpu(dsl->sl_offset))
  81. return false;
  82. if (size != be32_to_cpu(dsl->sl_bytes))
  83. return false;
  84. if (ino != be64_to_cpu(dsl->sl_owner))
  85. return false;
  86. /* ok */
  87. return true;
  88. }
  89. static bool
  90. xfs_symlink_verify(
  91. struct xfs_buf *bp)
  92. {
  93. struct xfs_mount *mp = bp->b_target->bt_mount;
  94. struct xfs_dsymlink_hdr *dsl = bp->b_addr;
  95. if (!xfs_sb_version_hascrc(&mp->m_sb))
  96. return false;
  97. if (dsl->sl_magic != cpu_to_be32(XFS_SYMLINK_MAGIC))
  98. return false;
  99. if (!uuid_equal(&dsl->sl_uuid, &mp->m_sb.sb_uuid))
  100. return false;
  101. if (bp->b_bn != be64_to_cpu(dsl->sl_blkno))
  102. return false;
  103. if (be32_to_cpu(dsl->sl_offset) +
  104. be32_to_cpu(dsl->sl_bytes) >= MAXPATHLEN)
  105. return false;
  106. if (dsl->sl_owner == 0)
  107. return false;
  108. return true;
  109. }
  110. static void
  111. xfs_symlink_read_verify(
  112. struct xfs_buf *bp)
  113. {
  114. struct xfs_mount *mp = bp->b_target->bt_mount;
  115. /* no verification of non-crc buffers */
  116. if (!xfs_sb_version_hascrc(&mp->m_sb))
  117. return;
  118. if (!xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length),
  119. offsetof(struct xfs_dsymlink_hdr, sl_crc)) ||
  120. !xfs_symlink_verify(bp)) {
  121. XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
  122. xfs_buf_ioerror(bp, EFSCORRUPTED);
  123. }
  124. }
  125. static void
  126. xfs_symlink_write_verify(
  127. struct xfs_buf *bp)
  128. {
  129. struct xfs_mount *mp = bp->b_target->bt_mount;
  130. struct xfs_buf_log_item *bip = bp->b_fspriv;
  131. /* no verification of non-crc buffers */
  132. if (!xfs_sb_version_hascrc(&mp->m_sb))
  133. return;
  134. if (!xfs_symlink_verify(bp)) {
  135. XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
  136. xfs_buf_ioerror(bp, EFSCORRUPTED);
  137. return;
  138. }
  139. if (bip) {
  140. struct xfs_dsymlink_hdr *dsl = bp->b_addr;
  141. dsl->sl_lsn = cpu_to_be64(bip->bli_item.li_lsn);
  142. }
  143. xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length),
  144. offsetof(struct xfs_dsymlink_hdr, sl_crc));
  145. }
  146. const struct xfs_buf_ops xfs_symlink_buf_ops = {
  147. .verify_read = xfs_symlink_read_verify,
  148. .verify_write = xfs_symlink_write_verify,
  149. };
  150. void
  151. xfs_symlink_local_to_remote(
  152. struct xfs_trans *tp,
  153. struct xfs_buf *bp,
  154. struct xfs_inode *ip,
  155. struct xfs_ifork *ifp)
  156. {
  157. struct xfs_mount *mp = ip->i_mount;
  158. char *buf;
  159. if (!xfs_sb_version_hascrc(&mp->m_sb)) {
  160. bp->b_ops = NULL;
  161. memcpy(bp->b_addr, ifp->if_u1.if_data, ifp->if_bytes);
  162. return;
  163. }
  164. /*
  165. * As this symlink fits in an inode literal area, it must also fit in
  166. * the smallest buffer the filesystem supports.
  167. */
  168. ASSERT(BBTOB(bp->b_length) >=
  169. ifp->if_bytes + sizeof(struct xfs_dsymlink_hdr));
  170. bp->b_ops = &xfs_symlink_buf_ops;
  171. buf = bp->b_addr;
  172. buf += xfs_symlink_hdr_set(mp, ip->i_ino, 0, ifp->if_bytes, bp);
  173. memcpy(buf, ifp->if_u1.if_data, ifp->if_bytes);
  174. }