From: Christoph Hellwig <hch@lst.de>
To: xfs@oss.sgi.com
Cc: viro@zeniv.linux.org.uk
Subject: [PATCH 6/6] xfs: optimize inline symlinks
Date: Thu, 23 Apr 2015 21:07:44 +0200 [thread overview]
Message-ID: <1429816064-10033-7-git-send-email-hch@lst.de> (raw)
In-Reply-To: <1429816064-10033-1-git-send-email-hch@lst.de>
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>
---
fs/xfs/libxfs/xfs_dir2_sf.c | 2 +-
fs/xfs/libxfs/xfs_inode_fork.c | 29 +++++++++++++++++++----------
fs/xfs/libxfs/xfs_inode_fork.h | 3 ++-
fs/xfs/xfs_inode_item.c | 4 ++--
fs/xfs/xfs_iops.c | 36 +-----------------------------------
fs/xfs/xfs_symlink.c | 5 +++--
6 files changed, 28 insertions(+), 51 deletions(-)
diff --git a/fs/xfs/libxfs/xfs_dir2_sf.c b/fs/xfs/libxfs/xfs_dir2_sf.c
index bf83116..a438058 100644
--- a/fs/xfs/libxfs/xfs_dir2_sf.c
+++ b/fs/xfs/libxfs/xfs_dir2_sf.c
@@ -258,7 +258,7 @@ xfs_dir2_block_to_sf(
* Convert the inode to local format and copy the data in.
*/
ASSERT(dp->i_df.if_bytes == 0);
- xfs_init_local_fork(dp, XFS_DATA_FORK, dst, size);
+ xfs_init_local_fork(dp, XFS_DATA_FORK, dst, size, false);
dp->i_d.di_format = XFS_DINODE_FMT_LOCAL;
dp->i_d.di_size = size;
diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c
index 86a3e11..dcadd07 100644
--- a/fs/xfs/libxfs/xfs_inode_fork.c
+++ b/fs/xfs/libxfs/xfs_inode_fork.c
@@ -235,22 +235,29 @@ xfs_init_local_fork(
struct xfs_inode *ip,
int whichfork,
const void *data,
- int size)
+ int size,
+ bool zero_terminate)
{
struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork);
- int real_size = 0;
+ int mem_size = size, real_size = 0;
+
+ if (zero_terminate)
+ mem_size = size + 1;
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;
@@ -270,11 +277,12 @@ xfs_init_local_fork(
*/
STATIC int
xfs_iformat_local(
- xfs_inode_t *ip,
- xfs_dinode_t *dip,
- int whichfork,
- int size)
+ struct xfs_inode *ip,
+ struct xfs_dinode *dip,
+ int whichfork,
+ int size)
{
+ bool zero_terminate = S_ISDIR(dip->di_mode);
/*
* If the size is unreasonable, then something
@@ -291,7 +299,8 @@ xfs_iformat_local(
return -EFSCORRUPTED;
}
- xfs_init_local_fork(ip, whichfork, XFS_DFORK_PTR(dip, whichfork), size);
+ xfs_init_local_fork(ip, whichfork, XFS_DFORK_PTR(dip, whichfork), size,
+ zero_terminate);
return 0;
}
diff --git a/fs/xfs/libxfs/xfs_inode_fork.h b/fs/xfs/libxfs/xfs_inode_fork.h
index dfb2966..f5f640f 100644
--- a/fs/xfs/libxfs/xfs_inode_fork.h
+++ b/fs/xfs/libxfs/xfs_inode_fork.h
@@ -135,7 +135,8 @@ void xfs_iroot_realloc(struct xfs_inode *, int, int);
int xfs_iread_extents(struct xfs_trans *, struct xfs_inode *, int);
int xfs_iextents_copy(struct xfs_inode *, struct xfs_bmbt_rec *,
int);
-void xfs_init_local_fork(struct xfs_inode *, int, const void *, int);
+void xfs_init_local_fork(struct xfs_inode *, int, const void *, int,
+ bool);
struct xfs_bmbt_rec_host *
xfs_iext_get_ext(struct xfs_ifork *, xfs_extnum_t);
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index bf13a5a..786d91a 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -210,7 +210,7 @@ xfs_inode_item_format_data_fork(
*/
data_bytes = roundup(ip->i_df.if_bytes, 4);
ASSERT(ip->i_df.if_real_bytes == 0 ||
- ip->i_df.if_real_bytes == data_bytes);
+ ip->i_df.if_real_bytes >= data_bytes);
ASSERT(ip->i_df.if_u1.if_data != NULL);
ASSERT(ip->i_d.di_size > 0);
xlog_copy_iovec(lv, vecp, XLOG_REG_TYPE_ILOCAL,
@@ -305,7 +305,7 @@ xfs_inode_item_format_attr_fork(
*/
data_bytes = roundup(ip->i_afp->if_bytes, 4);
ASSERT(ip->i_afp->if_real_bytes == 0 ||
- ip->i_afp->if_real_bytes == data_bytes);
+ ip->i_afp->if_real_bytes >= data_bytes);
ASSERT(ip->i_afp->if_u1.if_data != NULL);
xlog_copy_iovec(lv, vecp, XLOG_REG_TYPE_IATTR_LOCAL,
ip->i_afp->if_u1.if_data,
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index 57c0998..89e0cc9 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -413,45 +413,12 @@ xfs_vn_rename(
new_inode ? XFS_I(new_inode) : NULL, flags);
}
-/*
- * careful here - this function can get called recursively, so
- * we need to be very careful about how much stack we use.
- * uio is kmalloced for this reason...
- */
STATIC void *
xfs_vn_follow_link_inline(
struct dentry *dentry,
struct nameidata *nd)
{
- struct xfs_inode *ip = XFS_I(dentry->d_inode);
- xfs_fsize_t pathlen;
- char *link;
- int error = -ENOMEM;
-
- error = -ENOMEM;
- link = kmalloc(MAXPATHLEN+1, GFP_KERNEL);
- if (!link)
- goto out_err;
-
- error = -EIO;
- if (XFS_FORCED_SHUTDOWN(ip->i_mount))
- goto out_kfree;
-
- xfs_ilock(ip, XFS_ILOCK_SHARED);
- pathlen = ip->i_d.di_size;
- if (pathlen) {
- memcpy(link, ip->i_df.if_u1.if_data, pathlen);
- link[pathlen] = '\0';
- }
- xfs_iunlock(ip, XFS_ILOCK_SHARED);
-
- nd_set_link(nd, link);
- return NULL;
-
- out_kfree:
- kfree(link);
- out_err:
- nd_set_link(nd, ERR_PTR(error));
+ nd_set_link(nd, XFS_I(dentry->d_inode)->i_df.if_u1.if_data);
return NULL;
}
@@ -1204,7 +1171,6 @@ static const struct inode_operations xfs_symlink_inode_operations = {
static const struct inode_operations xfs_inline_symlink_inode_operations = {
.readlink = generic_readlink,
.follow_link = xfs_vn_follow_link_inline,
- .put_link = kfree_put_link,
.getattr = xfs_vn_getattr,
.setattr = xfs_vn_setattr,
.setxattr = generic_setxattr,
diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c
index c1d7775..d6b59f6 100644
--- a/fs/xfs/xfs_symlink.c
+++ b/fs/xfs/xfs_symlink.c
@@ -182,12 +182,13 @@ xfs_symlink(
if (resblks)
resblks -= XFS_IALLOC_SPACE_RES(mp);
+
/*
* If the symlink will fit into the inode, write it inline.
*/
if (pathlen <= XFS_IFORK_DSIZE(ip)) {
- xfs_init_local_fork(ip, XFS_DATA_FORK, target_path, pathlen);
-
+ xfs_init_local_fork(ip, XFS_DATA_FORK, target_path, pathlen,
+ true);
ip->i_d.di_size = pathlen;
ip->i_d.di_format = XFS_DINODE_FMT_LOCAL;
xfs_trans_log_inode(tp, ip, XFS_ILOG_DDATA | XFS_ILOG_CORE);
--
1.9.1
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
prev parent reply other threads:[~2015-04-23 19:09 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-04-23 19:07 optimize symlink handling Christoph Hellwig
2015-04-23 19:07 ` [PATCH 2/6] xfs: factor out a helper to initialize a local format inode fork Christoph Hellwig
2015-04-23 19:07 ` [PATCH 3/6] xfs: set up inode operation vectors later Christoph Hellwig
2015-04-23 19:07 ` [PATCH 4/6] xfs: use ->readlink to implement the readlink_by_handle ioctl Christoph Hellwig
2015-04-23 19:07 ` [PATCH 5/6] xfs: move non-inline symlinks to the pagecache Christoph Hellwig
2015-04-23 22:29 ` Dave Chinner
2015-04-24 8:21 ` Christoph Hellwig
2015-04-25 14:16 ` Christoph Hellwig
2015-04-25 14:57 ` Al Viro
2015-04-25 15:11 ` Al Viro
2015-04-25 18:32 ` Christoph Hellwig
2015-04-25 21:05 ` Al Viro
2015-04-23 19:07 ` Christoph Hellwig [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1429816064-10033-7-git-send-email-hch@lst.de \
--to=hch@lst.de \
--cc=viro@zeniv.linux.org.uk \
--cc=xfs@oss.sgi.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox