diff options
author | Christoph Hellwig <hch@lst.de> | 2016-04-06 07:53:29 +1000 |
---|---|---|
committer | Dave Chinner <david@fromorbit.com> | 2016-04-06 07:53:29 +1000 |
commit | 30ee052e12b97c190b27fe6f20e3ac3047df7b5c (patch) | |
tree | 92b34446e88e72e6ddce730b1f1b4192614a45be /fs/xfs/libxfs/xfs_inode_fork.c | |
parent | bfe8804d908a791b16e3686c101f0d7eca9fb5b9 (diff) | |
download | linux-30ee052e12b97c190b27fe6f20e3ac3047df7b5c.tar.bz2 |
xfs: optimize inline symlinks
By overallocating the in-core inode fork data buffer and zero
terminating the link target in xfs_init_local_fork we can avoid
the memory allocation in ->follow_link.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
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; |