summaryrefslogtreecommitdiff
path: root/fs/xfs/xfs_symlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_symlink.c')
-rw-r--r--fs/xfs/xfs_symlink.c29
1 files changed, 20 insertions, 9 deletions
diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c
index e41c8e8fcf9e..4ad97295bdfc 100644
--- a/fs/xfs/xfs_symlink.c
+++ b/fs/xfs/xfs_symlink.c
@@ -24,22 +24,21 @@
#include "xfs_ialloc.h"
#include "xfs_health.h"
#include "xfs_symlink_remote.h"
+#include "xfs_error.h"
/* ----- Kernel only functions below ----- */
int
xfs_readlink(
- struct xfs_inode *ip,
- char *link)
+ struct xfs_inode *ip,
+ char *link)
{
- struct xfs_mount *mp = ip->i_mount;
- xfs_fsize_t pathlen;
- int error = 0;
+ struct xfs_mount *mp = ip->i_mount;
+ xfs_fsize_t pathlen;
+ int error = 0;
trace_xfs_readlink(ip);
- ASSERT(ip->i_df.if_format != XFS_DINODE_FMT_LOCAL);
-
if (xfs_is_shutdown(mp))
return -EIO;
@@ -59,8 +58,20 @@ xfs_readlink(
goto out;
}
-
- error = xfs_symlink_remote_read(ip, link);
+ if (ip->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
+ /*
+ * The VFS crashes on a NULL pointer, so return -EFSCORRUPTED
+ * if if_data is junk.
+ */
+ if (XFS_IS_CORRUPT(ip->i_mount, !ip->i_df.if_u1.if_data)) {
+ xfs_inode_mark_sick(ip, XFS_SICK_INO_SYMLINK);
+ return error;
+ }
+
+ memcpy(link, ip->i_df.if_u1.if_data, pathlen + 1);
+ } else {
+ error = xfs_symlink_remote_read(ip, link);
+ }
out:
xfs_iunlock(ip, XFS_ILOCK_SHARED);