From: Christoph Hellwig Date: Tue, 21 Jun 2016 06:36:51 +0000 (+1000) Subject: xfs: optimize inline symlinks X-Git-Tag: v4.7.0-rc1~5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4cab415fc9e9b7d7b365c2e222b90b88a3053f01;p=thirdparty%2Fxfsprogs-dev.git xfs: optimize inline symlinks Source kernel commit 30ee052e12b97c190b27fe6f20e3ac3047df7b5c 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 Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- diff --git a/libxfs/xfs_inode_fork.c b/libxfs/xfs_inode_fork.c index 174333e93..8a59e2575 100644 --- a/libxfs/xfs_inode_fork.c +++ b/libxfs/xfs_inode_fork.c @@ -235,19 +235,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;