1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2000-2006 Silicon Graphics, Inc.
4 * Copyright (c) 2012-2013 Red Hat, Inc.
9 #include "xfs_format.h"
10 #include "xfs_log_format.h"
11 #include "xfs_shared.h"
12 #include "xfs_trans_resv.h"
13 #include "xfs_mount.h"
14 #include "xfs_inode.h"
15 #include "xfs_error.h"
16 #include "xfs_trans.h"
17 #include "xfs_buf_item.h"
19 #include "xfs_symlink_remote.h"
22 #include "xfs_health.h"
25 * Each contiguous block has a header, so it is not just a simple pathlen
33 int buflen = XFS_SYMLINK_BUF_SPACE(mp, mp->m_sb.sb_blocksize);
35 return (pathlen + buflen - 1) / buflen;
46 struct xfs_dsymlink_hdr *dsl = bp->b_addr;
51 memset(dsl, 0, sizeof(struct xfs_dsymlink_hdr));
52 dsl->sl_magic = cpu_to_be32(XFS_SYMLINK_MAGIC);
53 dsl->sl_offset = cpu_to_be32(offset);
54 dsl->sl_bytes = cpu_to_be32(size);
55 uuid_copy(&dsl->sl_uuid, &mp->m_sb.sb_meta_uuid);
56 dsl->sl_owner = cpu_to_be64(ino);
57 dsl->sl_blkno = cpu_to_be64(xfs_buf_daddr(bp));
58 bp->b_ops = &xfs_symlink_buf_ops;
60 return sizeof(struct xfs_dsymlink_hdr);
64 * Checking of the symlink header is split into two parts. the verifier does
65 * CRC, location and bounds checking, the unpacking function checks the path
66 * parameters and owner.
75 struct xfs_dsymlink_hdr *dsl = bp->b_addr;
77 if (offset != be32_to_cpu(dsl->sl_offset))
79 if (size != be32_to_cpu(dsl->sl_bytes))
81 if (ino != be64_to_cpu(dsl->sl_owner))
92 struct xfs_mount *mp = bp->b_mount;
93 struct xfs_dsymlink_hdr *dsl = bp->b_addr;
95 /* no verification of non-crc buffers */
99 if (!xfs_verify_magic(bp, dsl->sl_magic))
100 return __this_address;
101 if (!uuid_equal(&dsl->sl_uuid, &mp->m_sb.sb_meta_uuid))
102 return __this_address;
103 if (xfs_buf_daddr(bp) != be64_to_cpu(dsl->sl_blkno))
104 return __this_address;
105 if (be32_to_cpu(dsl->sl_offset) +
106 be32_to_cpu(dsl->sl_bytes) >= XFS_SYMLINK_MAXLEN)
107 return __this_address;
108 if (dsl->sl_owner == 0)
109 return __this_address;
110 if (!xfs_log_check_lsn(mp, be64_to_cpu(dsl->sl_lsn)))
111 return __this_address;
117 xfs_symlink_read_verify(
120 struct xfs_mount *mp = bp->b_mount;
123 /* no verification of non-crc buffers */
124 if (!xfs_has_crc(mp))
127 if (!xfs_buf_verify_cksum(bp, XFS_SYMLINK_CRC_OFF))
128 xfs_verifier_error(bp, -EFSBADCRC, __this_address);
130 fa = xfs_symlink_verify(bp);
132 xfs_verifier_error(bp, -EFSCORRUPTED, fa);
137 xfs_symlink_write_verify(
140 struct xfs_mount *mp = bp->b_mount;
141 struct xfs_buf_log_item *bip = bp->b_log_item;
144 /* no verification of non-crc buffers */
145 if (!xfs_has_crc(mp))
148 fa = xfs_symlink_verify(bp);
150 xfs_verifier_error(bp, -EFSCORRUPTED, fa);
155 struct xfs_dsymlink_hdr *dsl = bp->b_addr;
156 dsl->sl_lsn = cpu_to_be64(bip->bli_item.li_lsn);
158 xfs_buf_update_cksum(bp, XFS_SYMLINK_CRC_OFF);
161 const struct xfs_buf_ops xfs_symlink_buf_ops = {
162 .name = "xfs_symlink",
163 .magic = { 0, cpu_to_be32(XFS_SYMLINK_MAGIC) },
164 .verify_read = xfs_symlink_read_verify,
165 .verify_write = xfs_symlink_write_verify,
166 .verify_struct = xfs_symlink_verify,
170 xfs_symlink_local_to_remote(
171 struct xfs_trans *tp,
173 struct xfs_inode *ip,
174 struct xfs_ifork *ifp,
177 struct xfs_mount *mp = ip->i_mount;
180 xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SYMLINK_BUF);
182 if (!xfs_has_crc(mp)) {
184 memcpy(bp->b_addr, ifp->if_data, ifp->if_bytes);
185 xfs_trans_log_buf(tp, bp, 0, ifp->if_bytes - 1);
190 * As this symlink fits in an inode literal area, it must also fit in
191 * the smallest buffer the filesystem supports.
193 ASSERT(BBTOB(bp->b_length) >=
194 ifp->if_bytes + sizeof(struct xfs_dsymlink_hdr));
196 bp->b_ops = &xfs_symlink_buf_ops;
199 buf += xfs_symlink_hdr_set(mp, ip->i_ino, 0, ifp->if_bytes, bp);
200 memcpy(buf, ifp->if_data, ifp->if_bytes);
201 xfs_trans_log_buf(tp, bp, 0, sizeof(struct xfs_dsymlink_hdr) +
206 * Verify the in-memory consistency of an inline symlink data fork. This
207 * does not do on-disk format checks.
210 xfs_symlink_shortform_verify(
214 char *endp = sfp + size;
217 * Zero length symlinks should never occur in memory as they are
218 * never allowed to exist on disk.
221 return __this_address;
223 /* No negative sizes or overly long symlink targets. */
224 if (size < 0 || size > XFS_SYMLINK_MAXLEN)
225 return __this_address;
227 /* No NULLs in the target either. */
228 if (memchr(sfp, 0, size - 1))
229 return __this_address;
231 /* We /did/ null-terminate the buffer, right? */
233 return __this_address;
237 /* Read a remote symlink target into the buffer. */
239 xfs_symlink_remote_read(
240 struct xfs_inode *ip,
243 struct xfs_mount *mp = ip->i_mount;
244 struct xfs_bmbt_irec mval[XFS_SYMLINK_MAPS];
248 int pathlen = ip->i_disk_size;
249 int nmaps = XFS_SYMLINK_MAPS;
256 xfs_assert_ilocked(ip, XFS_ILOCK_SHARED | XFS_ILOCK_EXCL);
258 fsblocks = xfs_symlink_blocks(mp, pathlen);
259 error = xfs_bmapi_read(ip, 0, fsblocks, mval, &nmaps, 0);
264 for (n = 0; n < nmaps; n++) {
265 d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock);
266 byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
268 error = xfs_buf_read(mp->m_ddev_targp, d, BTOBB(byte_cnt), 0,
269 &bp, &xfs_symlink_buf_ops);
270 if (xfs_metadata_is_sick(error))
271 xfs_inode_mark_sick(ip, XFS_SICK_INO_SYMLINK);
274 byte_cnt = XFS_SYMLINK_BUF_SPACE(mp, byte_cnt);
275 if (pathlen < byte_cnt)
278 cur_chunk = bp->b_addr;
279 if (xfs_has_crc(mp)) {
280 if (!xfs_symlink_hdr_ok(ip->i_ino, offset,
282 xfs_inode_mark_sick(ip, XFS_SICK_INO_SYMLINK);
283 error = -EFSCORRUPTED;
285 "symlink header does not match required off/len/owner (0x%x/0x%x,0x%llx)",
286 offset, byte_cnt, ip->i_ino);
292 cur_chunk += sizeof(struct xfs_dsymlink_hdr);
295 memcpy(link + offset, cur_chunk, byte_cnt);
302 ASSERT(pathlen == 0);
304 link[ip->i_disk_size] = '\0';
311 /* Write the symlink target into the inode. */
313 xfs_symlink_write_target(
314 struct xfs_trans *tp,
315 struct xfs_inode *ip,
317 const char *target_path,
319 xfs_fsblock_t fs_blocks,
322 struct xfs_bmbt_irec mval[XFS_SYMLINK_MAPS];
323 struct xfs_mount *mp = tp->t_mountp;
324 const char *cur_chunk;
334 * If the symlink will fit into the inode, write it inline.
336 if (pathlen <= xfs_inode_data_fork_size(ip)) {
337 xfs_init_local_fork(ip, XFS_DATA_FORK, target_path, pathlen);
339 ip->i_disk_size = pathlen;
340 ip->i_df.if_format = XFS_DINODE_FMT_LOCAL;
341 xfs_trans_log_inode(tp, ip, XFS_ILOG_DDATA | XFS_ILOG_CORE);
345 nmaps = XFS_SYMLINK_MAPS;
346 error = xfs_bmapi_write(tp, ip, 0, fs_blocks, XFS_BMAPI_METADATA,
347 resblks, mval, &nmaps);
351 ip->i_disk_size = pathlen;
352 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
354 cur_chunk = target_path;
356 for (n = 0; n < nmaps; n++) {
359 d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock);
360 byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
361 error = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
362 BTOBB(byte_cnt), 0, &bp);
365 bp->b_ops = &xfs_symlink_buf_ops;
367 byte_cnt = XFS_SYMLINK_BUF_SPACE(mp, byte_cnt);
368 byte_cnt = min(byte_cnt, pathlen);
371 buf += xfs_symlink_hdr_set(mp, owner, offset, byte_cnt, bp);
373 memcpy(buf, cur_chunk, byte_cnt);
375 cur_chunk += byte_cnt;
379 xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SYMLINK_BUF);
380 xfs_trans_log_buf(tp, bp, 0, (buf + byte_cnt - 1) -
383 ASSERT(pathlen == 0);
387 /* Remove all the blocks from a symlink and invalidate buffers. */
389 xfs_symlink_remote_truncate(
390 struct xfs_trans *tp,
391 struct xfs_inode *ip)
393 struct xfs_bmbt_irec mval[XFS_SYMLINK_MAPS];
394 struct xfs_mount *mp = tp->t_mountp;
396 int nmaps = XFS_SYMLINK_MAPS;
401 /* Read mappings and invalidate buffers. */
402 error = xfs_bmapi_read(ip, 0, XFS_MAX_FILEOFF, mval, &nmaps, 0);
406 for (i = 0; i < nmaps; i++) {
407 if (!xfs_bmap_is_real_extent(&mval[i]))
410 error = xfs_trans_get_buf(tp, mp->m_ddev_targp,
411 XFS_FSB_TO_DADDR(mp, mval[i].br_startblock),
412 XFS_FSB_TO_BB(mp, mval[i].br_blockcount), 0,
417 xfs_trans_binval(tp, bp);
420 /* Unmap the remote blocks. */
421 error = xfs_bunmapi(tp, ip, 0, XFS_MAX_FILEOFF, 0, nmaps, &done);
426 xfs_inode_mark_sick(ip, XFS_SICK_INO_SYMLINK);
427 return -EFSCORRUPTED;
430 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);