* [PATCH 1/4] xfs: factor out a helper to initialize a local format inode fork
2016-03-23 13:48 support RCU lookups for inline symlinks Christoph Hellwig
@ 2016-03-23 13:48 ` Christoph Hellwig
2016-03-23 13:48 ` [PATCH 2/4] xfs: set up inode operation vectors later Christoph Hellwig
` (3 subsequent siblings)
4 siblings, 0 replies; 10+ messages in thread
From: Christoph Hellwig @ 2016-03-23 13:48 UTC (permalink / raw)
To: xfs
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/xfs/libxfs/xfs_dir2_sf.c | 9 +++-----
fs/xfs/libxfs/xfs_inode_fork.c | 48 ++++++++++++++++++++++++++----------------
fs/xfs/libxfs/xfs_inode_fork.h | 1 +
fs/xfs/xfs_symlink.c | 12 ++---------
4 files changed, 36 insertions(+), 34 deletions(-)
diff --git a/fs/xfs/libxfs/xfs_dir2_sf.c b/fs/xfs/libxfs/xfs_dir2_sf.c
index 974d62e..e5bb9cc 100644
--- a/fs/xfs/libxfs/xfs_dir2_sf.c
+++ b/fs/xfs/libxfs/xfs_dir2_sf.c
@@ -257,15 +257,12 @@ xfs_dir2_block_to_sf(
*
* Convert the inode to local format and copy the data in.
*/
- dp->i_df.if_flags &= ~XFS_IFEXTENTS;
- dp->i_df.if_flags |= XFS_IFINLINE;
- dp->i_d.di_format = XFS_DINODE_FMT_LOCAL;
ASSERT(dp->i_df.if_bytes == 0);
- xfs_idata_realloc(dp, size, XFS_DATA_FORK);
+ xfs_init_local_fork(dp, XFS_DATA_FORK, dst, size);
+ dp->i_d.di_format = XFS_DINODE_FMT_LOCAL;
+ dp->i_d.di_size = size;
logflags |= XFS_ILOG_DDATA;
- memcpy(dp->i_df.if_u1.if_data, dst, size);
- dp->i_d.di_size = size;
xfs_dir2_sf_check(args);
out:
xfs_trans_log_inode(args->trans, dp, logflags);
diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c
index 11faf7d..86a97f8 100644
--- a/fs/xfs/libxfs/xfs_inode_fork.c
+++ b/fs/xfs/libxfs/xfs_inode_fork.c
@@ -231,6 +231,34 @@ xfs_iformat_fork(
return error;
}
+void
+xfs_init_local_fork(
+ struct xfs_inode *ip,
+ int whichfork,
+ const void *data,
+ int size)
+{
+ struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork);
+ int real_size = 0;
+
+ if (size == 0)
+ ifp->if_u1.if_data = NULL;
+ else if (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);
+ ifp->if_u1.if_data = kmem_alloc(real_size, KM_SLEEP | KM_NOFS);
+ }
+
+ if (size)
+ memcpy(ifp->if_u1.if_data, data, size);
+
+ ifp->if_bytes = size;
+ ifp->if_real_bytes = real_size;
+ ifp->if_flags &= ~(XFS_IFEXTENTS | XFS_IFBROOT);
+ ifp->if_flags |= XFS_IFINLINE;
+}
+
/*
* The file is in-lined in the on-disk inode.
* If it fits into if_inline_data, then copy
@@ -248,8 +276,6 @@ xfs_iformat_local(
int whichfork,
int size)
{
- xfs_ifork_t *ifp;
- int real_size;
/*
* If the size is unreasonable, then something
@@ -265,22 +291,8 @@ xfs_iformat_local(
ip->i_mount, dip);
return -EFSCORRUPTED;
}
- ifp = XFS_IFORK_PTR(ip, whichfork);
- real_size = 0;
- if (size == 0)
- ifp->if_u1.if_data = NULL;
- else if (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);
- ifp->if_u1.if_data = kmem_alloc(real_size, KM_SLEEP | KM_NOFS);
- }
- ifp->if_bytes = size;
- ifp->if_real_bytes = real_size;
- if (size)
- memcpy(ifp->if_u1.if_data, XFS_DFORK_PTR(dip, whichfork), size);
- ifp->if_flags &= ~XFS_IFEXTENTS;
- ifp->if_flags |= XFS_IFINLINE;
+
+ xfs_init_local_fork(ip, whichfork, XFS_DFORK_PTR(dip, whichfork), size);
return 0;
}
diff --git a/fs/xfs/libxfs/xfs_inode_fork.h b/fs/xfs/libxfs/xfs_inode_fork.h
index 7d3b1ed..f95e072 100644
--- a/fs/xfs/libxfs/xfs_inode_fork.h
+++ b/fs/xfs/libxfs/xfs_inode_fork.h
@@ -134,6 +134,7 @@ 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);
struct xfs_bmbt_rec_host *
xfs_iext_get_ext(struct xfs_ifork *, xfs_extnum_t);
diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c
index b44284c..b69f4a7 100644
--- a/fs/xfs/xfs_symlink.c
+++ b/fs/xfs/xfs_symlink.c
@@ -302,19 +302,11 @@ xfs_symlink(
* If the symlink will fit into the inode, write it inline.
*/
if (pathlen <= XFS_IFORK_DSIZE(ip)) {
- xfs_idata_realloc(ip, pathlen, XFS_DATA_FORK);
- memcpy(ip->i_df.if_u1.if_data, target_path, pathlen);
- ip->i_d.di_size = pathlen;
-
- /*
- * The inode was initially created in extent format.
- */
- ip->i_df.if_flags &= ~(XFS_IFEXTENTS | XFS_IFBROOT);
- ip->i_df.if_flags |= XFS_IFINLINE;
+ xfs_init_local_fork(ip, XFS_DATA_FORK, target_path, pathlen);
+ 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);
-
} else {
int offset;
--
2.1.4
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH 2/4] xfs: set up inode operation vectors later
2016-03-23 13:48 support RCU lookups for inline symlinks Christoph Hellwig
2016-03-23 13:48 ` [PATCH 1/4] xfs: factor out a helper to initialize a local format inode fork Christoph Hellwig
@ 2016-03-23 13:48 ` Christoph Hellwig
2016-03-23 23:05 ` Dave Chinner
2016-03-23 13:48 ` [PATCH 3/4] xfs: use ->readlink to implement the readlink_by_handle ioctl Christoph Hellwig
` (2 subsequent siblings)
4 siblings, 1 reply; 10+ messages in thread
From: Christoph Hellwig @ 2016-03-23 13:48 UTC (permalink / raw)
To: xfs
In the next patch we'll set up different inode operations for inline vs
out of line symlinks, for that we need to make sure the flags are already
set up properly.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/xfs/xfs_inode.h | 5 ++++-
fs/xfs/xfs_iops.c | 59 ++++++++++++++++++++++++++++++++++--------------------
2 files changed, 41 insertions(+), 23 deletions(-)
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 43e1d51..e52d7c7 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -440,6 +440,9 @@ loff_t __xfs_seek_hole_data(struct inode *inode, loff_t start,
/* from xfs_iops.c */
+extern void xfs_setup_inode(struct xfs_inode *ip);
+extern void xfs_setup_iops(struct xfs_inode *ip);
+
/*
* When setting up a newly allocated inode, we need to call
* xfs_finish_inode_setup() once the inode is fully instantiated at
@@ -447,7 +450,6 @@ loff_t __xfs_seek_hole_data(struct inode *inode, loff_t start,
* before we've completed instantiation. Otherwise we can do it
* the moment the inode lookup is complete.
*/
-extern void xfs_setup_inode(struct xfs_inode *ip);
static inline void xfs_finish_inode_setup(struct xfs_inode *ip)
{
xfs_iflags_clear(ip, XFS_INEW);
@@ -458,6 +460,7 @@ static inline void xfs_finish_inode_setup(struct xfs_inode *ip)
static inline void xfs_setup_existing_inode(struct xfs_inode *ip)
{
xfs_setup_inode(ip);
+ xfs_setup_iops(ip);
xfs_finish_inode_setup(ip);
}
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index fb7dc61..f08d91c 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -181,6 +181,8 @@ xfs_generic_create(
}
#endif
+ xfs_setup_iops(ip);
+
if (tmpfile)
d_tmpfile(dentry, inode);
else
@@ -368,6 +370,8 @@ xfs_vn_symlink(
if (unlikely(error))
goto out_cleanup_inode;
+ xfs_setup_iops(cip);
+
d_instantiate(dentry, inode);
xfs_finish_inode_setup(cip);
return 0;
@@ -1193,7 +1197,7 @@ xfs_diflags_to_iflags(
}
/*
- * Initialize the Linux inode and set up the operation vectors.
+ * Initialize the Linux inode.
*
* When reading existing inodes from disk this is called directly from xfs_iget,
* when creating a new inode it is called from xfs_ialloc after setting up the
@@ -1232,8 +1236,38 @@ xfs_setup_inode(
i_size_write(inode, ip->i_d.di_size);
xfs_diflags_to_iflags(inode, ip);
- ip->d_ops = ip->i_mount->m_nondir_inode_ops;
- lockdep_set_class(&ip->i_lock.mr_lock, &xfs_nondir_ilock_class);
+ if (S_ISDIR(inode->i_mode)) {
+ lockdep_set_class(&ip->i_lock.mr_lock, &xfs_dir_ilock_class);
+ ip->d_ops = ip->i_mount->m_dir_inode_ops;
+ } else {
+ ip->d_ops = ip->i_mount->m_nondir_inode_ops;
+ lockdep_set_class(&ip->i_lock.mr_lock, &xfs_nondir_ilock_class);
+ }
+
+ /*
+ * Ensure all page cache allocations are done from GFP_NOFS context to
+ * prevent direct reclaim recursion back into the filesystem and blowing
+ * stacks or deadlocking.
+ */
+ gfp_mask = mapping_gfp_mask(inode->i_mapping);
+ mapping_set_gfp_mask(inode->i_mapping, (gfp_mask & ~(__GFP_FS)));
+
+ /*
+ * If there is no attribute fork no ACL can exist on this inode,
+ * and it can't have any file capabilities attached to it either.
+ */
+ if (!XFS_IFORK_Q(ip)) {
+ inode_has_no_xattr(inode);
+ cache_no_acl(inode);
+ }
+}
+
+void
+xfs_setup_iops(
+ struct xfs_inode *ip)
+{
+ struct inode *inode = &ip->i_vnode;
+
switch (inode->i_mode & S_IFMT) {
case S_IFREG:
inode->i_op = &xfs_inode_operations;
@@ -1241,13 +1275,11 @@ xfs_setup_inode(
inode->i_mapping->a_ops = &xfs_address_space_operations;
break;
case S_IFDIR:
- lockdep_set_class(&ip->i_lock.mr_lock, &xfs_dir_ilock_class);
if (xfs_sb_version_hasasciici(&XFS_M(inode->i_sb)->m_sb))
inode->i_op = &xfs_dir_ci_inode_operations;
else
inode->i_op = &xfs_dir_inode_operations;
inode->i_fop = &xfs_dir_file_operations;
- ip->d_ops = ip->i_mount->m_dir_inode_ops;
break;
case S_IFLNK:
inode->i_op = &xfs_symlink_inode_operations;
@@ -1259,21 +1291,4 @@ xfs_setup_inode(
init_special_inode(inode, inode->i_mode, inode->i_rdev);
break;
}
-
- /*
- * Ensure all page cache allocations are done from GFP_NOFS context to
- * prevent direct reclaim recursion back into the filesystem and blowing
- * stacks or deadlocking.
- */
- gfp_mask = mapping_gfp_mask(inode->i_mapping);
- mapping_set_gfp_mask(inode->i_mapping, (gfp_mask & ~(__GFP_FS)));
-
- /*
- * If there is no attribute fork no ACL can exist on this inode,
- * and it can't have any file capabilities attached to it either.
- */
- if (!XFS_IFORK_Q(ip)) {
- inode_has_no_xattr(inode);
- cache_no_acl(inode);
- }
}
--
2.1.4
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 10+ messages in thread* Re: [PATCH 2/4] xfs: set up inode operation vectors later
2016-03-23 13:48 ` [PATCH 2/4] xfs: set up inode operation vectors later Christoph Hellwig
@ 2016-03-23 23:05 ` Dave Chinner
2016-03-23 23:26 ` Christoph Hellwig
0 siblings, 1 reply; 10+ messages in thread
From: Dave Chinner @ 2016-03-23 23:05 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: xfs
On Wed, Mar 23, 2016 at 02:48:53PM +0100, Christoph Hellwig wrote:
> In the next patch we'll set up different inode operations for inline vs
> out of line symlinks, for that we need to make sure the flags are already
> set up properly.
....
> diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
> index fb7dc61..f08d91c 100644
> --- a/fs/xfs/xfs_iops.c
> +++ b/fs/xfs/xfs_iops.c
> @@ -181,6 +181,8 @@ xfs_generic_create(
> }
> #endif
>
> + xfs_setup_iops(ip);
> +
> if (tmpfile)
> d_tmpfile(dentry, inode);
> else
> @@ -368,6 +370,8 @@ xfs_vn_symlink(
> if (unlikely(error))
> goto out_cleanup_inode;
>
> + xfs_setup_iops(cip);
> +
> d_instantiate(dentry, inode);
> xfs_finish_inode_setup(cip);
I think there are more places than this that need xfs_setup_iops()
calls - a quick look around makes me think they need to be paired
with every path that calls xfs_finish_inode_setup().
Cheers,
Dave.
--
Dave Chinner
david@fromorbit.com
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/4] xfs: set up inode operation vectors later
2016-03-23 23:05 ` Dave Chinner
@ 2016-03-23 23:26 ` Christoph Hellwig
2016-03-23 23:45 ` Dave Chinner
0 siblings, 1 reply; 10+ messages in thread
From: Christoph Hellwig @ 2016-03-23 23:26 UTC (permalink / raw)
To: Dave Chinner; +Cc: Christoph Hellwig, xfs
On Thu, Mar 24, 2016 at 10:05:00AM +1100, Dave Chinner wrote:
> > d_instantiate(dentry, inode);
> > xfs_finish_inode_setup(cip);
>
> I think there are more places than this that need xfs_setup_iops()
> calls - a quick look around makes me think they need to be paired
> with every path that calls xfs_finish_inode_setup().
Most calls to xfs_finish_inode_setup are for error cases that
just drop the inode instantly and don't need it. The other
cases are:
- xfs_generic_create, xfs_vn_symlink and xfs_setup_existing_inode,
which are handled in this patch
- xfs_qm_qino_alloc, which is for the quota inode that doesn't have
inode operations
- xfs_rename_alloc_whiteout which probably needs it. This seems
to be recent and has no apparent test coverage, so I'm not sure
how to verify it, though.
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/4] xfs: set up inode operation vectors later
2016-03-23 23:26 ` Christoph Hellwig
@ 2016-03-23 23:45 ` Dave Chinner
0 siblings, 0 replies; 10+ messages in thread
From: Dave Chinner @ 2016-03-23 23:45 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: xfs
On Thu, Mar 24, 2016 at 12:26:30AM +0100, Christoph Hellwig wrote:
> On Thu, Mar 24, 2016 at 10:05:00AM +1100, Dave Chinner wrote:
> > > d_instantiate(dentry, inode);
> > > xfs_finish_inode_setup(cip);
> >
> > I think there are more places than this that need xfs_setup_iops()
> > calls - a quick look around makes me think they need to be paired
> > with every path that calls xfs_finish_inode_setup().
>
> Most calls to xfs_finish_inode_setup are for error cases that
> just drop the inode instantly and don't need it.
Fair enough.
> The other
> cases are:
>
> - xfs_generic_create, xfs_vn_symlink and xfs_setup_existing_inode,
> which are handled in this patch
> - xfs_qm_qino_alloc, which is for the quota inode that doesn't have
> inode operations
*nod*
> - xfs_rename_alloc_whiteout which probably needs it. This seems
> to be recent and has no apparent test coverage, so I'm not sure
> how to verify it, though.
Yup, that's the one I first noticed. generic/078 tests
RENAME_WHITEOUT functionality through renameat2() and it includes
operations on symlinks, so there is some coverage in xfstests for
it.
Cheers,
Dave.
--
Dave Chinner
david@fromorbit.com
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 3/4] xfs: use ->readlink to implement the readlink_by_handle ioctl
2016-03-23 13:48 support RCU lookups for inline symlinks Christoph Hellwig
2016-03-23 13:48 ` [PATCH 1/4] xfs: factor out a helper to initialize a local format inode fork Christoph Hellwig
2016-03-23 13:48 ` [PATCH 2/4] xfs: set up inode operation vectors later Christoph Hellwig
@ 2016-03-23 13:48 ` Christoph Hellwig
2016-03-23 13:48 ` [PATCH 4/4] xfs: optimize inline symlinks Christoph Hellwig
2016-04-05 21:55 ` support RCU lookups for " Dave Chinner
4 siblings, 0 replies; 10+ messages in thread
From: Christoph Hellwig @ 2016-03-23 13:48 UTC (permalink / raw)
To: xfs
Also drop the now unused readlink_copy export.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/namei.c | 1 -
fs/xfs/xfs_ioctl.c | 18 ++----------------
2 files changed, 2 insertions(+), 17 deletions(-)
diff --git a/fs/namei.c b/fs/namei.c
index f624d13..33b02dd 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -4554,7 +4554,6 @@ int readlink_copy(char __user *buffer, int buflen, const char *link)
out:
return len;
}
-EXPORT_SYMBOL(readlink_copy);
/*
* A helper for ->readlink(). This should be used *ONLY* for symlinks that
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index bcb6c19..68569b8 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -277,7 +277,6 @@ xfs_readlink_by_handle(
{
struct dentry *dentry;
__u32 olen;
- void *link;
int error;
if (!capable(CAP_SYS_ADMIN))
@@ -288,7 +287,7 @@ xfs_readlink_by_handle(
return PTR_ERR(dentry);
/* Restrict this handle operation to symlinks only. */
- if (!d_is_symlink(dentry)) {
+ if (!dentry->d_inode->i_op->readlink) {
error = -EINVAL;
goto out_dput;
}
@@ -298,21 +297,8 @@ xfs_readlink_by_handle(
goto out_dput;
}
- link = kmalloc(MAXPATHLEN+1, GFP_KERNEL);
- if (!link) {
- error = -ENOMEM;
- goto out_dput;
- }
-
- error = xfs_readlink(XFS_I(d_inode(dentry)), link);
- if (error)
- goto out_kfree;
- error = readlink_copy(hreq->ohandle, olen, link);
- if (error)
- goto out_kfree;
+ error = dentry->d_inode->i_op->readlink(dentry, hreq->ohandle, olen);
- out_kfree:
- kfree(link);
out_dput:
dput(dentry);
return error;
--
2.1.4
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH 4/4] xfs: optimize inline symlinks
2016-03-23 13:48 support RCU lookups for inline symlinks Christoph Hellwig
` (2 preceding siblings ...)
2016-03-23 13:48 ` [PATCH 3/4] xfs: use ->readlink to implement the readlink_by_handle ioctl Christoph Hellwig
@ 2016-03-23 13:48 ` Christoph Hellwig
2016-04-05 21:55 ` support RCU lookups for " Dave Chinner
4 siblings, 0 replies; 10+ messages in thread
From: Christoph Hellwig @ 2016-03-23 13:48 UTC (permalink / raw)
To: xfs
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_inode_fork.c | 22 ++++++++++++++++++----
fs/xfs/xfs_inode_item.c | 4 ++--
fs/xfs/xfs_iops.c | 29 ++++++++++++++++++++++++++---
fs/xfs/xfs_symlink.c | 9 +++------
4 files changed, 49 insertions(+), 15 deletions(-)
diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c
index 86a97f8..4fbe226 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;
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index c48b5b1..37e23c7 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 f08d91c..aee06d9 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -446,6 +446,16 @@ xfs_vn_get_link(
return ERR_PTR(error);
}
+STATIC const char *
+xfs_vn_get_link_inline(
+ struct dentry *dentry,
+ struct inode *inode,
+ struct delayed_call *done)
+{
+ ASSERT(XFS_I(inode)->i_df.if_flags & XFS_IFINLINE);
+ return XFS_I(inode)->i_df.if_u1.if_data;
+}
+
STATIC int
xfs_vn_getattr(
struct vfsmount *mnt,
@@ -1171,6 +1181,18 @@ static const struct inode_operations xfs_symlink_inode_operations = {
.update_time = xfs_vn_update_time,
};
+static const struct inode_operations xfs_inline_symlink_inode_operations = {
+ .readlink = generic_readlink,
+ .get_link = xfs_vn_get_link_inline,
+ .getattr = xfs_vn_getattr,
+ .setattr = xfs_vn_setattr,
+ .setxattr = generic_setxattr,
+ .getxattr = generic_getxattr,
+ .removexattr = generic_removexattr,
+ .listxattr = xfs_vn_listxattr,
+ .update_time = xfs_vn_update_time,
+};
+
STATIC void
xfs_diflags_to_iflags(
struct inode *inode,
@@ -1282,9 +1304,10 @@ xfs_setup_iops(
inode->i_fop = &xfs_dir_file_operations;
break;
case S_IFLNK:
- inode->i_op = &xfs_symlink_inode_operations;
- if (!(ip->i_df.if_flags & XFS_IFINLINE))
- inode->i_mapping->a_ops = &xfs_address_space_operations;
+ if (ip->i_df.if_flags & XFS_IFINLINE)
+ inode->i_op = &xfs_inline_symlink_inode_operations;
+ else
+ inode->i_op = &xfs_symlink_inode_operations;
break;
default:
inode->i_op = &xfs_inode_operations;
diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c
index b69f4a7..5961c1e 100644
--- a/fs/xfs/xfs_symlink.c
+++ b/fs/xfs/xfs_symlink.c
@@ -131,6 +131,8 @@ xfs_readlink(
trace_xfs_readlink(ip);
+ ASSERT(!(ip->i_df.if_flags & XFS_IFINLINE));
+
if (XFS_FORCED_SHUTDOWN(mp))
return -EIO;
@@ -150,12 +152,7 @@ xfs_readlink(
}
- if (ip->i_df.if_flags & XFS_IFINLINE) {
- memcpy(link, ip->i_df.if_u1.if_data, pathlen);
- link[pathlen] = '\0';
- } else {
- error = xfs_readlink_bmap(ip, link);
- }
+ error = xfs_readlink_bmap(ip, link);
out:
xfs_iunlock(ip, XFS_ILOCK_SHARED);
--
2.1.4
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 10+ messages in thread* Re: support RCU lookups for inline symlinks
2016-03-23 13:48 support RCU lookups for inline symlinks Christoph Hellwig
` (3 preceding siblings ...)
2016-03-23 13:48 ` [PATCH 4/4] xfs: optimize inline symlinks Christoph Hellwig
@ 2016-04-05 21:55 ` Dave Chinner
2016-04-07 23:21 ` Christoph Hellwig
4 siblings, 1 reply; 10+ messages in thread
From: Dave Chinner @ 2016-04-05 21:55 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: xfs
On Wed, Mar 23, 2016 at 02:48:51PM +0100, Christoph Hellwig wrote:
> Return the inline link body in the inode to support RCU mode lookups.
The series doesn't appear to cause any regressions and the code
looks good, so I've added the missing xfs_setup_iops() call in
xfs_rename_alloc_whiteout() (patch 2), and converted dentry->d_inode
to d_inode(dentry) in patch 3 for consistency withe the rest of the
code and committed this series.
Cheers,
Dave.
--
Dave Chinner
david@fromorbit.com
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: support RCU lookups for inline symlinks
2016-04-05 21:55 ` support RCU lookups for " Dave Chinner
@ 2016-04-07 23:21 ` Christoph Hellwig
0 siblings, 0 replies; 10+ messages in thread
From: Christoph Hellwig @ 2016-04-07 23:21 UTC (permalink / raw)
To: Dave Chinner; +Cc: xfs
On Wed, Apr 06, 2016 at 07:55:08AM +1000, Dave Chinner wrote:
> On Wed, Mar 23, 2016 at 02:48:51PM +0100, Christoph Hellwig wrote:
> > Return the inline link body in the inode to support RCU mode lookups.
>
> The series doesn't appear to cause any regressions and the code
> looks good, so I've added the missing xfs_setup_iops() call in
> xfs_rename_alloc_whiteout() (patch 2), and converted dentry->d_inode
> to d_inode(dentry) in patch 3 for consistency withe the rest of the
> code and committed this series.
Thanks. After some pondering I think we should setup the iops for the
quota inodes as well - if we ever do something like vfs_getattr on them
now that we're using VFS inode everywhere we'll need it. And I'd better
be prepared for that than finding bugs after I've forgotten about all
this. I'll send an incremental patch.
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 10+ messages in thread