Skip to content

Commit 376b4f0

Browse files
author
Darrick J. Wong
committed
xfs: move remote symlink target read function to libxfs
Move xfs_readlink_bmap_ilocked to xfs_symlink_remote.c so that the swapext code can use it to convert a remote format symlink back to shortform format after a metadata repair. While we're at it, fix a broken printf prefix. Signed-off-by: Darrick J. Wong <djwong@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de>
1 parent 622d88e commit 376b4f0

File tree

5 files changed

+80
-77
lines changed

5 files changed

+80
-77
lines changed

fs/xfs/libxfs/xfs_symlink_remote.c

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
#include "xfs_buf_item.h"
1818
#include "xfs_log.h"
1919
#include "xfs_symlink_remote.h"
20+
#include "xfs_bit.h"
21+
#include "xfs_bmap.h"
22+
#include "xfs_health.h"
2023

2124
/*
2225
* Each contiguous block has a header, so it is not just a simple pathlen
@@ -227,3 +230,77 @@ xfs_symlink_shortform_verify(
227230
return __this_address;
228231
return NULL;
229232
}
233+
234+
/* Read a remote symlink target into the buffer. */
235+
int
236+
xfs_symlink_remote_read(
237+
struct xfs_inode *ip,
238+
char *link)
239+
{
240+
struct xfs_mount *mp = ip->i_mount;
241+
struct xfs_bmbt_irec mval[XFS_SYMLINK_MAPS];
242+
struct xfs_buf *bp;
243+
xfs_daddr_t d;
244+
char *cur_chunk;
245+
int pathlen = ip->i_disk_size;
246+
int nmaps = XFS_SYMLINK_MAPS;
247+
int byte_cnt;
248+
int n;
249+
int error = 0;
250+
int fsblocks = 0;
251+
int offset;
252+
253+
xfs_assert_ilocked(ip, XFS_ILOCK_SHARED | XFS_ILOCK_EXCL);
254+
255+
fsblocks = xfs_symlink_blocks(mp, pathlen);
256+
error = xfs_bmapi_read(ip, 0, fsblocks, mval, &nmaps, 0);
257+
if (error)
258+
goto out;
259+
260+
offset = 0;
261+
for (n = 0; n < nmaps; n++) {
262+
d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock);
263+
byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
264+
265+
error = xfs_buf_read(mp->m_ddev_targp, d, BTOBB(byte_cnt), 0,
266+
&bp, &xfs_symlink_buf_ops);
267+
if (xfs_metadata_is_sick(error))
268+
xfs_inode_mark_sick(ip, XFS_SICK_INO_SYMLINK);
269+
if (error)
270+
return error;
271+
byte_cnt = XFS_SYMLINK_BUF_SPACE(mp, byte_cnt);
272+
if (pathlen < byte_cnt)
273+
byte_cnt = pathlen;
274+
275+
cur_chunk = bp->b_addr;
276+
if (xfs_has_crc(mp)) {
277+
if (!xfs_symlink_hdr_ok(ip->i_ino, offset,
278+
byte_cnt, bp)) {
279+
xfs_inode_mark_sick(ip, XFS_SICK_INO_SYMLINK);
280+
error = -EFSCORRUPTED;
281+
xfs_alert(mp,
282+
"symlink header does not match required off/len/owner (0x%x/0x%x,0x%llx)",
283+
offset, byte_cnt, ip->i_ino);
284+
xfs_buf_relse(bp);
285+
goto out;
286+
287+
}
288+
289+
cur_chunk += sizeof(struct xfs_dsymlink_hdr);
290+
}
291+
292+
memcpy(link + offset, cur_chunk, byte_cnt);
293+
294+
pathlen -= byte_cnt;
295+
offset += byte_cnt;
296+
297+
xfs_buf_relse(bp);
298+
}
299+
ASSERT(pathlen == 0);
300+
301+
link[ip->i_disk_size] = '\0';
302+
error = 0;
303+
304+
out:
305+
return error;
306+
}

fs/xfs/libxfs/xfs_symlink_remote.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,6 @@ bool xfs_symlink_hdr_ok(xfs_ino_t ino, uint32_t offset,
1818
void xfs_symlink_local_to_remote(struct xfs_trans *tp, struct xfs_buf *bp,
1919
struct xfs_inode *ip, struct xfs_ifork *ifp);
2020
xfs_failaddr_t xfs_symlink_shortform_verify(void *sfp, int64_t size);
21+
int xfs_symlink_remote_read(struct xfs_inode *ip, char *link);
2122

2223
#endif /* __XFS_SYMLINK_REMOTE_H */

fs/xfs/scrub/symlink.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ xchk_symlink(
6868
}
6969

7070
/* Remote symlink; must read the contents. */
71-
error = xfs_readlink_bmap_ilocked(sc->ip, sc->buf);
71+
error = xfs_symlink_remote_read(sc->ip, sc->buf);
7272
if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, 0, &error))
7373
return error;
7474
if (strnlen(sc->buf, XFS_SYMLINK_MAXLEN) < len)

fs/xfs/xfs_symlink.c

Lines changed: 1 addition & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -26,80 +26,6 @@
2626
#include "xfs_health.h"
2727
#include "xfs_symlink_remote.h"
2828

29-
/* ----- Kernel only functions below ----- */
30-
int
31-
xfs_readlink_bmap_ilocked(
32-
struct xfs_inode *ip,
33-
char *link)
34-
{
35-
struct xfs_mount *mp = ip->i_mount;
36-
struct xfs_bmbt_irec mval[XFS_SYMLINK_MAPS];
37-
struct xfs_buf *bp;
38-
xfs_daddr_t d;
39-
char *cur_chunk;
40-
int pathlen = ip->i_disk_size;
41-
int nmaps = XFS_SYMLINK_MAPS;
42-
int byte_cnt;
43-
int n;
44-
int error = 0;
45-
int fsblocks = 0;
46-
int offset;
47-
48-
xfs_assert_ilocked(ip, XFS_ILOCK_SHARED | XFS_ILOCK_EXCL);
49-
50-
fsblocks = xfs_symlink_blocks(mp, pathlen);
51-
error = xfs_bmapi_read(ip, 0, fsblocks, mval, &nmaps, 0);
52-
if (error)
53-
goto out;
54-
55-
offset = 0;
56-
for (n = 0; n < nmaps; n++) {
57-
d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock);
58-
byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
59-
60-
error = xfs_buf_read(mp->m_ddev_targp, d, BTOBB(byte_cnt), 0,
61-
&bp, &xfs_symlink_buf_ops);
62-
if (xfs_metadata_is_sick(error))
63-
xfs_inode_mark_sick(ip, XFS_SICK_INO_SYMLINK);
64-
if (error)
65-
return error;
66-
byte_cnt = XFS_SYMLINK_BUF_SPACE(mp, byte_cnt);
67-
if (pathlen < byte_cnt)
68-
byte_cnt = pathlen;
69-
70-
cur_chunk = bp->b_addr;
71-
if (xfs_has_crc(mp)) {
72-
if (!xfs_symlink_hdr_ok(ip->i_ino, offset,
73-
byte_cnt, bp)) {
74-
xfs_inode_mark_sick(ip, XFS_SICK_INO_SYMLINK);
75-
error = -EFSCORRUPTED;
76-
xfs_alert(mp,
77-
"symlink header does not match required off/len/owner (0x%x/Ox%x,0x%llx)",
78-
offset, byte_cnt, ip->i_ino);
79-
xfs_buf_relse(bp);
80-
goto out;
81-
82-
}
83-
84-
cur_chunk += sizeof(struct xfs_dsymlink_hdr);
85-
}
86-
87-
memcpy(link + offset, cur_chunk, byte_cnt);
88-
89-
pathlen -= byte_cnt;
90-
offset += byte_cnt;
91-
92-
xfs_buf_relse(bp);
93-
}
94-
ASSERT(pathlen == 0);
95-
96-
link[ip->i_disk_size] = '\0';
97-
error = 0;
98-
99-
out:
100-
return error;
101-
}
102-
10329
int
10430
xfs_readlink(
10531
struct xfs_inode *ip,
@@ -141,7 +67,7 @@ xfs_readlink(
14167
memcpy(link, ip->i_df.if_data, pathlen + 1);
14268
error = 0;
14369
} else {
144-
error = xfs_readlink_bmap_ilocked(ip, link);
70+
error = xfs_symlink_remote_read(ip, link);
14571
}
14672

14773
xfs_iunlock(ip, XFS_ILOCK_SHARED);

fs/xfs/xfs_symlink.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
int xfs_symlink(struct mnt_idmap *idmap, struct xfs_inode *dp,
1111
struct xfs_name *link_name, const char *target_path,
1212
umode_t mode, struct xfs_inode **ipp);
13-
int xfs_readlink_bmap_ilocked(struct xfs_inode *ip, char *link);
1413
int xfs_readlink(struct xfs_inode *ip, char *link);
1514
int xfs_inactive_symlink(struct xfs_inode *ip);
1615

0 commit comments

Comments
 (0)