symlink.c 1.6 KB
Newer Older
D
Dave Chinner 已提交
1
// SPDX-License-Identifier: GPL-2.0+
D
Darrick J. Wong 已提交
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/*
 * Copyright (C) 2017 Oracle.  All Rights Reserved.
 * Author: Darrick J. Wong <darrick.wong@oracle.com>
 */
#include "xfs.h"
#include "xfs_fs.h"
#include "xfs_shared.h"
#include "xfs_format.h"
#include "xfs_trans_resv.h"
#include "xfs_mount.h"
#include "xfs_log_format.h"
#include "xfs_inode.h"
#include "xfs_symlink.h"
#include "scrub/scrub.h"
#include "scrub/common.h"

/* Set us up to scrub a symbolic link. */
int
D
Darrick J. Wong 已提交
20
xchk_setup_symlink(
21
	struct xfs_scrub	*sc,
22
	struct xfs_inode	*ip)
D
Darrick J. Wong 已提交
23 24
{
	/* Allocate the buffer without the inode lock held. */
25
	sc->buf = kvzalloc(XFS_SYMLINK_MAXLEN + 1, GFP_KERNEL);
D
Darrick J. Wong 已提交
26 27 28
	if (!sc->buf)
		return -ENOMEM;

D
Darrick J. Wong 已提交
29
	return xchk_setup_inode_contents(sc, ip, 0);
D
Darrick J. Wong 已提交
30 31 32 33 34
}

/* Symbolic links. */

int
D
Darrick J. Wong 已提交
35
xchk_symlink(
36
	struct xfs_scrub	*sc)
D
Darrick J. Wong 已提交
37
{
38 39 40 41
	struct xfs_inode	*ip = sc->ip;
	struct xfs_ifork	*ifp;
	loff_t			len;
	int			error = 0;
D
Darrick J. Wong 已提交
42 43 44 45

	if (!S_ISLNK(VFS_I(ip)->i_mode))
		return -ENOENT;
	ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
46
	len = ip->i_disk_size;
D
Darrick J. Wong 已提交
47 48 49

	/* Plausible size? */
	if (len > XFS_SYMLINK_MAXLEN || len <= 0) {
D
Darrick J. Wong 已提交
50
		xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
D
Darrick J. Wong 已提交
51 52 53 54 55 56 57
		goto out;
	}

	/* Inline symlink? */
	if (ifp->if_flags & XFS_IFINLINE) {
		if (len > XFS_IFORK_DSIZE(ip) ||
		    len > strnlen(ifp->if_u1.if_data, XFS_IFORK_DSIZE(ip)))
D
Darrick J. Wong 已提交
58
			xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
D
Darrick J. Wong 已提交
59 60 61 62 63
		goto out;
	}

	/* Remote symlink; must read the contents. */
	error = xfs_readlink_bmap_ilocked(sc->ip, sc->buf);
D
Darrick J. Wong 已提交
64
	if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, 0, &error))
D
Darrick J. Wong 已提交
65 66
		goto out;
	if (strnlen(sc->buf, XFS_SYMLINK_MAXLEN) < len)
D
Darrick J. Wong 已提交
67
		xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
D
Darrick J. Wong 已提交
68 69 70
out:
	return error;
}