xfs_symlink_remote.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  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_format.h"
  23. #include "xfs_shared.h"
  24. #include "xfs_trans_resv.h"
  25. #include "xfs_ag.h"
  26. #include "xfs_sb.h"
  27. #include "xfs_mount.h"
  28. #include "xfs_bmap_btree.h"
  29. #include "xfs_inode.h"
  30. #include "xfs_error.h"
  31. #include "xfs_trace.h"
  32. #include "xfs_symlink.h"
  33. #include "xfs_cksum.h"
  34. #include "xfs_trans.h"
  35. #include "xfs_buf_item.h"
  36. /*
  37. * Each contiguous block has a header, so it is not just a simple pathlen
  38. * to FSB conversion.
  39. */
  40. int
  41. xfs_symlink_blocks(
  42. struct xfs_mount *mp,
  43. int pathlen)
  44. {
  45. int buflen = XFS_SYMLINK_BUF_SPACE(mp, mp->m_sb.sb_blocksize);
  46. return (pathlen + buflen - 1) / buflen;
  47. }
  48. int
  49. xfs_symlink_hdr_set(
  50. struct xfs_mount *mp,
  51. xfs_ino_t ino,
  52. uint32_t offset,
  53. uint32_t size,
  54. struct xfs_buf *bp)
  55. {
  56. struct xfs_dsymlink_hdr *dsl = bp->b_addr;
  57. if (!xfs_sb_version_hascrc(&mp->m_sb))
  58. return 0;
  59. dsl->sl_magic = cpu_to_be32(XFS_SYMLINK_MAGIC);
  60. dsl->sl_offset = cpu_to_be32(offset);
  61. dsl->sl_bytes = cpu_to_be32(size);
  62. uuid_copy(&dsl->sl_uuid, &mp->m_sb.sb_uuid);
  63. dsl->sl_owner = cpu_to_be64(ino);
  64. dsl->sl_blkno = cpu_to_be64(bp->b_bn);
  65. bp->b_ops = &xfs_symlink_buf_ops;
  66. return sizeof(struct xfs_dsymlink_hdr);
  67. }
  68. /*
  69. * Checking of the symlink header is split into two parts. the verifier does
  70. * CRC, location and bounds checking, the unpacking function checks the path
  71. * parameters and owner.
  72. */
  73. bool
  74. xfs_symlink_hdr_ok(
  75. struct xfs_mount *mp,
  76. xfs_ino_t ino,
  77. uint32_t offset,
  78. uint32_t size,
  79. struct xfs_buf *bp)
  80. {
  81. struct xfs_dsymlink_hdr *dsl = bp->b_addr;
  82. if (offset != be32_to_cpu(dsl->sl_offset))
  83. return false;
  84. if (size != be32_to_cpu(dsl->sl_bytes))
  85. return false;
  86. if (ino != be64_to_cpu(dsl->sl_owner))
  87. return false;
  88. /* ok */
  89. return true;
  90. }
  91. static bool
  92. xfs_symlink_verify(
  93. struct xfs_buf *bp)
  94. {
  95. struct xfs_mount *mp = bp->b_target->bt_mount;
  96. struct xfs_dsymlink_hdr *dsl = bp->b_addr;
  97. if (!xfs_sb_version_hascrc(&mp->m_sb))
  98. return false;
  99. if (dsl->sl_magic != cpu_to_be32(XFS_SYMLINK_MAGIC))
  100. return false;
  101. if (!uuid_equal(&dsl->sl_uuid, &mp->m_sb.sb_uuid))
  102. return false;
  103. if (bp->b_bn != be64_to_cpu(dsl->sl_blkno))
  104. return false;
  105. if (be32_to_cpu(dsl->sl_offset) +
  106. be32_to_cpu(dsl->sl_bytes) >= MAXPATHLEN)
  107. return false;
  108. if (dsl->sl_owner == 0)
  109. return false;
  110. return true;
  111. }
  112. static void
  113. xfs_symlink_read_verify(
  114. struct xfs_buf *bp)
  115. {
  116. struct xfs_mount *mp = bp->b_target->bt_mount;
  117. /* no verification of non-crc buffers */
  118. if (!xfs_sb_version_hascrc(&mp->m_sb))
  119. return;
  120. if (!xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length),
  121. offsetof(struct xfs_dsymlink_hdr, sl_crc)) ||
  122. !xfs_symlink_verify(bp)) {
  123. XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
  124. xfs_buf_ioerror(bp, EFSCORRUPTED);
  125. }
  126. }
  127. static void
  128. xfs_symlink_write_verify(
  129. struct xfs_buf *bp)
  130. {
  131. struct xfs_mount *mp = bp->b_target->bt_mount;
  132. struct xfs_buf_log_item *bip = bp->b_fspriv;
  133. /* no verification of non-crc buffers */
  134. if (!xfs_sb_version_hascrc(&mp->m_sb))
  135. return;
  136. if (!xfs_symlink_verify(bp)) {
  137. XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
  138. xfs_buf_ioerror(bp, EFSCORRUPTED);
  139. return;
  140. }
  141. if (bip) {
  142. struct xfs_dsymlink_hdr *dsl = bp->b_addr;
  143. dsl->sl_lsn = cpu_to_be64(bip->bli_item.li_lsn);
  144. }
  145. xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length),
  146. offsetof(struct xfs_dsymlink_hdr, sl_crc));
  147. }
  148. const struct xfs_buf_ops xfs_symlink_buf_ops = {
  149. .verify_read = xfs_symlink_read_verify,
  150. .verify_write = xfs_symlink_write_verify,
  151. };
  152. void
  153. xfs_symlink_local_to_remote(
  154. struct xfs_trans *tp,
  155. struct xfs_buf *bp,
  156. struct xfs_inode *ip,
  157. struct xfs_ifork *ifp)
  158. {
  159. struct xfs_mount *mp = ip->i_mount;
  160. char *buf;
  161. if (!xfs_sb_version_hascrc(&mp->m_sb)) {
  162. bp->b_ops = NULL;
  163. memcpy(bp->b_addr, ifp->if_u1.if_data, ifp->if_bytes);
  164. return;
  165. }
  166. /*
  167. * As this symlink fits in an inode literal area, it must also fit in
  168. * the smallest buffer the filesystem supports.
  169. */
  170. ASSERT(BBTOB(bp->b_length) >=
  171. ifp->if_bytes + sizeof(struct xfs_dsymlink_hdr));
  172. bp->b_ops = &xfs_symlink_buf_ops;
  173. buf = bp->b_addr;
  174. buf += xfs_symlink_hdr_set(mp, ip->i_ino, 0, ifp->if_bytes, bp);
  175. memcpy(buf, ifp->if_u1.if_data, ifp->if_bytes);
  176. }