]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs: optimize inline symlinks
authorChristoph Hellwig <hch@lst.de>
Tue, 21 Jun 2016 06:36:51 +0000 (16:36 +1000)
committerDave Chinner <david@fromorbit.com>
Tue, 21 Jun 2016 06:36:51 +0000 (16:36 +1000)
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 <hch@lst.de>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
libxfs/xfs_inode_fork.c

index 174333e93ff78d89b5e0da5e7866e71a5e6a36c7..8a59e2575b471e81fff3b672de0f7b8492e19e7e 100644 (file)
@@ -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;