Skip to content

Commit e6469b2

Browse files
author
Chandan Babu R
committed
Merge tag 'symlink-cleanups-6.9_2024-02-23' of https://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux into xfs-6.9-mergeC
xfs: clean up symbolic link code This series cleans up a few bits of the symbolic link code as needed for future projects. Online repair requires the ability to commit fixed fork-based filesystem metadata such as directories, xattrs, and symbolic links atomically, so we need to rearrange the symlink code before we land the atomic extent swapping. Accomplish this by moving the remote symlink target block code and declarations to xfs_symlink_remote.[ch]. Signed-off-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Chandan Babu R <chandanbabu@kernel.org> * tag 'symlink-cleanups-6.9_2024-02-23' of https://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux: xfs: move symlink target write function to libxfs xfs: move remote symlink target read function to libxfs xfs: move xfs_symlink_remote.c declarations to xfs_symlink_remote.h
2 parents 6723ca9 + b8102b6 commit e6469b2

File tree

9 files changed

+192
-155
lines changed

9 files changed

+192
-155
lines changed

fs/xfs/libxfs/xfs_bmap.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "xfs_iomap.h"
3939
#include "xfs_health.h"
4040
#include "xfs_bmap_item.h"
41+
#include "xfs_symlink_remote.h"
4142

4243
struct kmem_cache *xfs_bmap_intent_cache;
4344

fs/xfs/libxfs/xfs_inode_fork.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "xfs_types.h"
2727
#include "xfs_errortag.h"
2828
#include "xfs_health.h"
29+
#include "xfs_symlink_remote.h"
2930

3031
struct kmem_cache *xfs_ifork_cache;
3132

fs/xfs/libxfs/xfs_shared.h

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -182,19 +182,6 @@ void xfs_log_get_max_trans_res(struct xfs_mount *mp,
182182
#define XFS_ICHGTIME_CHG 0x2 /* inode field change timestamp */
183183
#define XFS_ICHGTIME_CREATE 0x4 /* inode create timestamp */
184184

185-
186-
/*
187-
* Symlink decoding/encoding functions
188-
*/
189-
int xfs_symlink_blocks(struct xfs_mount *mp, int pathlen);
190-
int xfs_symlink_hdr_set(struct xfs_mount *mp, xfs_ino_t ino, uint32_t offset,
191-
uint32_t size, struct xfs_buf *bp);
192-
bool xfs_symlink_hdr_ok(xfs_ino_t ino, uint32_t offset,
193-
uint32_t size, struct xfs_buf *bp);
194-
void xfs_symlink_local_to_remote(struct xfs_trans *tp, struct xfs_buf *bp,
195-
struct xfs_inode *ip, struct xfs_ifork *ifp);
196-
xfs_failaddr_t xfs_symlink_shortform_verify(void *sfp, int64_t size);
197-
198185
/* Computed inode geometry for the filesystem. */
199186
struct xfs_ino_geometry {
200187
/* Maximum inode count in this filesystem. */

fs/xfs/libxfs/xfs_symlink_remote.c

Lines changed: 154 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@
1616
#include "xfs_trans.h"
1717
#include "xfs_buf_item.h"
1818
#include "xfs_log.h"
19-
19+
#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,153 @@ 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+
}
307+
308+
/* Write the symlink target into the inode. */
309+
int
310+
xfs_symlink_write_target(
311+
struct xfs_trans *tp,
312+
struct xfs_inode *ip,
313+
const char *target_path,
314+
int pathlen,
315+
xfs_fsblock_t fs_blocks,
316+
uint resblks)
317+
{
318+
struct xfs_bmbt_irec mval[XFS_SYMLINK_MAPS];
319+
struct xfs_mount *mp = tp->t_mountp;
320+
const char *cur_chunk;
321+
struct xfs_buf *bp;
322+
xfs_daddr_t d;
323+
int byte_cnt;
324+
int nmaps;
325+
int offset = 0;
326+
int n;
327+
int error;
328+
329+
/*
330+
* If the symlink will fit into the inode, write it inline.
331+
*/
332+
if (pathlen <= xfs_inode_data_fork_size(ip)) {
333+
xfs_init_local_fork(ip, XFS_DATA_FORK, target_path, pathlen);
334+
335+
ip->i_disk_size = pathlen;
336+
ip->i_df.if_format = XFS_DINODE_FMT_LOCAL;
337+
xfs_trans_log_inode(tp, ip, XFS_ILOG_DDATA | XFS_ILOG_CORE);
338+
return 0;
339+
}
340+
341+
nmaps = XFS_SYMLINK_MAPS;
342+
error = xfs_bmapi_write(tp, ip, 0, fs_blocks, XFS_BMAPI_METADATA,
343+
resblks, mval, &nmaps);
344+
if (error)
345+
return error;
346+
347+
ip->i_disk_size = pathlen;
348+
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
349+
350+
cur_chunk = target_path;
351+
offset = 0;
352+
for (n = 0; n < nmaps; n++) {
353+
char *buf;
354+
355+
d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock);
356+
byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
357+
error = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
358+
BTOBB(byte_cnt), 0, &bp);
359+
if (error)
360+
return error;
361+
bp->b_ops = &xfs_symlink_buf_ops;
362+
363+
byte_cnt = XFS_SYMLINK_BUF_SPACE(mp, byte_cnt);
364+
byte_cnt = min(byte_cnt, pathlen);
365+
366+
buf = bp->b_addr;
367+
buf += xfs_symlink_hdr_set(mp, ip->i_ino, offset, byte_cnt,
368+
bp);
369+
370+
memcpy(buf, cur_chunk, byte_cnt);
371+
372+
cur_chunk += byte_cnt;
373+
pathlen -= byte_cnt;
374+
offset += byte_cnt;
375+
376+
xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SYMLINK_BUF);
377+
xfs_trans_log_buf(tp, bp, 0, (buf + byte_cnt - 1) -
378+
(char *)bp->b_addr);
379+
}
380+
ASSERT(pathlen == 0);
381+
return 0;
382+
}

fs/xfs/libxfs/xfs_symlink_remote.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
4+
* Copyright (c) 2013 Red Hat, Inc.
5+
* All Rights Reserved.
6+
*/
7+
#ifndef __XFS_SYMLINK_REMOTE_H
8+
#define __XFS_SYMLINK_REMOTE_H
9+
10+
/*
11+
* Symlink decoding/encoding functions
12+
*/
13+
int xfs_symlink_blocks(struct xfs_mount *mp, int pathlen);
14+
int xfs_symlink_hdr_set(struct xfs_mount *mp, xfs_ino_t ino, uint32_t offset,
15+
uint32_t size, struct xfs_buf *bp);
16+
bool xfs_symlink_hdr_ok(xfs_ino_t ino, uint32_t offset,
17+
uint32_t size, struct xfs_buf *bp);
18+
void xfs_symlink_local_to_remote(struct xfs_trans *tp, struct xfs_buf *bp,
19+
struct xfs_inode *ip, struct xfs_ifork *ifp);
20+
xfs_failaddr_t xfs_symlink_shortform_verify(void *sfp, int64_t size);
21+
int xfs_symlink_remote_read(struct xfs_inode *ip, char *link);
22+
int xfs_symlink_write_target(struct xfs_trans *tp, struct xfs_inode *ip,
23+
const char *target_path, int pathlen, xfs_fsblock_t fs_blocks,
24+
uint resblks);
25+
26+
#endif /* __XFS_SYMLINK_REMOTE_H */

fs/xfs/scrub/inode_repair.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "xfs_attr_leaf.h"
3838
#include "xfs_log_priv.h"
3939
#include "xfs_health.h"
40+
#include "xfs_symlink_remote.h"
4041
#include "scrub/xfs_scrub.h"
4142
#include "scrub/scrub.h"
4243
#include "scrub/common.h"

fs/xfs/scrub/symlink.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "xfs_inode.h"
1414
#include "xfs_symlink.h"
1515
#include "xfs_health.h"
16+
#include "xfs_symlink_remote.h"
1617
#include "scrub/scrub.h"
1718
#include "scrub/common.h"
1819
#include "scrub/health.h"
@@ -67,7 +68,7 @@ xchk_symlink(
6768
}
6869

6970
/* Remote symlink; must read the contents. */
70-
error = xfs_readlink_bmap_ilocked(sc->ip, sc->buf);
71+
error = xfs_symlink_remote_read(sc->ip, sc->buf);
7172
if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, 0, &error))
7273
return error;
7374
if (strnlen(sc->buf, XFS_SYMLINK_MAXLEN) < len)

0 commit comments

Comments
 (0)