diff options
Diffstat (limited to 'fs/xfs/libxfs/xfs_inode_fork.c')
-rw-r--r-- | fs/xfs/libxfs/xfs_inode_fork.c | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c index 86a97f8a9de3..4fbe2263c1fc 100644 --- a/fs/xfs/libxfs/xfs_inode_fork.c +++ b/fs/xfs/libxfs/xfs_inode_fork.c @@ -239,19 +239,33 @@ xfs_init_local_fork( int size) { struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork); - int real_size = 0; + int mem_size = size, real_size = 0; + bool zero_terminate; + + /* + * If we are using the local fork to store a symlink body we need to + * zero-terminate it so that we can pass it back to the VFS directly. + * Overallocate the in-memory fork by one for that and add a zero + * to terminate it below. + */ + zero_terminate = S_ISLNK(VFS_I(ip)->i_mode); + if (zero_terminate) + mem_size++; if (size == 0) ifp->if_u1.if_data = NULL; - else if (size <= sizeof(ifp->if_u2.if_inline_data)) + else if (mem_size <= sizeof(ifp->if_u2.if_inline_data)) ifp->if_u1.if_data = ifp->if_u2.if_inline_data; else { - real_size = roundup(size, 4); + real_size = roundup(mem_size, 4); ifp->if_u1.if_data = kmem_alloc(real_size, KM_SLEEP | KM_NOFS); } - if (size) + if (size) { memcpy(ifp->if_u1.if_data, data, size); + if (zero_terminate) + ifp->if_u1.if_data[size] = '\0'; + } ifp->if_bytes = size; ifp->if_real_bytes = real_size; |