diff mbox

[RFC,2/8] xfs: introduce extents to local conversion helper

Message ID 1530846750-6686-3-git-send-email-shan.hai@oracle.com (mailing list archive)
State New, archived
Headers show

Commit Message

Shan Hai July 6, 2018, 3:12 a.m. UTC
Delete the extents from xfs inode, copy the data into the data fork,
convert the inode from extents to local format and specify log the
core and data fork of the inode.

Signed-off-by: Shan Hai <shan.hai@oracle.com>
---
 fs/xfs/libxfs/xfs_bmap.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++-
 fs/xfs/libxfs/xfs_bmap.h |  4 ++++
 2 files changed, 63 insertions(+), 1 deletion(-)

Comments

Darrick J. Wong July 6, 2018, 3:45 a.m. UTC | #1
On Fri, Jul 06, 2018 at 11:12:23AM +0800, Shan Hai wrote:
> Delete the extents from xfs inode, copy the data into the data fork,
> convert the inode from extents to local format and specify log the
> core and data fork of the inode.
> 
> Signed-off-by: Shan Hai <shan.hai@oracle.com>
> ---
>  fs/xfs/libxfs/xfs_bmap.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++-
>  fs/xfs/libxfs/xfs_bmap.h |  4 ++++
>  2 files changed, 63 insertions(+), 1 deletion(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
> index 7205268b30bc..bea6dc254a7d 100644
> --- a/fs/xfs/libxfs/xfs_bmap.c
> +++ b/fs/xfs/libxfs/xfs_bmap.c
> @@ -1,6 +1,7 @@
>  // SPDX-License-Identifier: GPL-2.0
>  /*
>   * Copyright (c) 2000-2006 Silicon Graphics, Inc.
> + * Copyright (c) 2018 Oracle.
>   * All Rights Reserved.
>   */
>  #include "xfs.h"
> @@ -213,7 +214,7 @@ xfs_default_attroffset(
>   * attribute fork from local to extent format - we reset it where
>   * possible to make space available for inline data fork extents.
>   */
> -STATIC void
> +void
>  xfs_bmap_forkoff_reset(

Unrelated change in this patch?

Also, is it safe to reset forkoff when converting the data fork to
extents?  Does doing so mes up the attr fork?

>  	xfs_inode_t	*ip,
>  	int		whichfork)
> @@ -5141,6 +5142,63 @@ xfs_bmap_del_extent_real(
>  }
>  
>  /*
> + * Convert an inode from extents to the local format.
> + * Free all the extents of the inode and reset it to the local
> + * format. Copy the contents of the inode's blocks to the inode's
> + * literal area.
> + */
> +int
> +xfs_bmap_extents_to_local(
> +	xfs_trans_t		*tp,
> +	xfs_inode_t		*ip,

No typedefs, please.

	struct xfs_inode	*ip,

> +	struct xfs_defer_ops	*dfops,
> +	int			*logflagsp,
> +	int			whichfork,
> +	struct page		*page)
> +{
> +	xfs_ifork_t		*ifp = XFS_IFORK_PTR(ip, whichfork);
> +	xfs_fileoff_t		isize = i_size_read(VFS_I(ip));
> +	struct xfs_bmbt_irec	got, del;
> +	struct xfs_iext_cursor	icur;
> +	int			error = 0;
> +	int			tmp_logflags;
> +	char			*kaddr = NULL;
> +
> +	ASSERT(whichfork != XFS_COW_FORK);
> +	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS);
> +
> +	if (xfs_iext_count(ifp) == 0)
> +		goto init_local_fork;
> +
> +	for_each_xfs_iext(ifp, &icur, &got) {
> +		del = got;
> +		if (isnullstartblock(got.br_startblock)) {
> +			error = xfs_bmap_del_extent_delay(ip,
> +					whichfork, &icur, &got, &del);
> +			if (error)
> +				goto out;
> +		} else {
> +			error = xfs_bmap_del_extent_real(ip, tp, &icur, dfops,
> +					NULL, &del, &tmp_logflags, whichfork, 0);
> +			if (error)
> +				goto out;
> +			*logflagsp |= tmp_logflags;
> +		}
> +	}
> +init_local_fork:
> +	kaddr = kmap_atomic(page);
> +	xfs_init_local_fork(ip, whichfork, kaddr, isize);
> +	kunmap_atomic(kaddr);
> +	ip->i_d.di_format = XFS_DINODE_FMT_LOCAL;
> +	XFS_IFORK_NEXT_SET(ip, whichfork, 0);
> +	ip->i_d.di_size = isize;
> +	*logflagsp |= (XFS_ILOG_DDATA | XFS_ILOG_CORE);
> +out:
> +	return error;
> +}
> +
> +
> +/*
>   * Unmap (remove) blocks from a file.
>   * If nexts is nonzero then the number of extents to remove is limited to
>   * that value.  If not all extents in the block range can be removed then
> diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h
> index 9b49ddf99c41..22cd2642f1cd 100644
> --- a/fs/xfs/libxfs/xfs_bmap.h
> +++ b/fs/xfs/libxfs/xfs_bmap.h
> @@ -271,6 +271,10 @@ int	xfs_bmap_map_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
>  		struct xfs_inode *ip, struct xfs_bmbt_irec *imap);
>  int	xfs_bmap_unmap_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
>  		struct xfs_inode *ip, struct xfs_bmbt_irec *imap);
> +int	xfs_bmap_extents_to_local(struct xfs_trans *tp, struct xfs_inode *ip,
> +		struct xfs_defer_ops *dfops, int *flags, int whichfork,
> +		struct page *page);
> +void	xfs_bmap_forkoff_reset(struct xfs_inode *ip, int whichfork);
>  
>  static inline int xfs_bmap_fork_to_state(int whichfork)
>  {
> -- 
> 2.11.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Shan Hai July 6, 2018, 4:15 a.m. UTC | #2
On 2018年07月06日 11:45, Darrick J. Wong wrote:
> On Fri, Jul 06, 2018 at 11:12:23AM +0800, Shan Hai wrote:
>> Delete the extents from xfs inode, copy the data into the data fork,
>> convert the inode from extents to local format and specify log the
>> core and data fork of the inode.
>>
>> Signed-off-by: Shan Hai <shan.hai@oracle.com>
>> ---
>>   fs/xfs/libxfs/xfs_bmap.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++-
>>   fs/xfs/libxfs/xfs_bmap.h |  4 ++++
>>   2 files changed, 63 insertions(+), 1 deletion(-)
>>
>> diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
>> index 7205268b30bc..bea6dc254a7d 100644
>> --- a/fs/xfs/libxfs/xfs_bmap.c
>> +++ b/fs/xfs/libxfs/xfs_bmap.c
>> @@ -1,6 +1,7 @@
>>   // SPDX-License-Identifier: GPL-2.0
>>   /*
>>    * Copyright (c) 2000-2006 Silicon Graphics, Inc.
>> + * Copyright (c) 2018 Oracle.
>>    * All Rights Reserved.
>>    */
>>   #include "xfs.h"
>> @@ -213,7 +214,7 @@ xfs_default_attroffset(
>>    * attribute fork from local to extent format - we reset it where
>>    * possible to make space available for inline data fork extents.
>>    */
>> -STATIC void
>> +void
>>   xfs_bmap_forkoff_reset(
> Unrelated change in this patch?

Need this in the 3rd patch to convert the inode from extents to local, 
so export it,
because I thought that the conversion function should reside in the 
xfs_file.c instead
of xfs_bmap.c.

> Also, is it safe to reset forkoff when converting the data fork to
> extents?  Does doing so mes up the attr fork?
>

The attr fork should be aware the forkoff changes, I will double check 
this anyway.

Thanks
Shan Hai
>>   	xfs_inode_t	*ip,
>>   	int		whichfork)
>> @@ -5141,6 +5142,63 @@ xfs_bmap_del_extent_real(
>>   }
>>   
>>   /*
>> + * Convert an inode from extents to the local format.
>> + * Free all the extents of the inode and reset it to the local
>> + * format. Copy the contents of the inode's blocks to the inode's
>> + * literal area.
>> + */
>> +int
>> +xfs_bmap_extents_to_local(
>> +	xfs_trans_t		*tp,
>> +	xfs_inode_t		*ip,
> No typedefs, please.
>
> 	struct xfs_inode	*ip,

OK, I will fix it.

Thanks
Shan Hai
>> +	struct xfs_defer_ops	*dfops,
>> +	int			*logflagsp,
>> +	int			whichfork,
>> +	struct page		*page)
>> +{
>> +	xfs_ifork_t		*ifp = XFS_IFORK_PTR(ip, whichfork);
>> +	xfs_fileoff_t		isize = i_size_read(VFS_I(ip));
>> +	struct xfs_bmbt_irec	got, del;
>> +	struct xfs_iext_cursor	icur;
>> +	int			error = 0;
>> +	int			tmp_logflags;
>> +	char			*kaddr = NULL;
>> +
>> +	ASSERT(whichfork != XFS_COW_FORK);
>> +	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS);
>> +
>> +	if (xfs_iext_count(ifp) == 0)
>> +		goto init_local_fork;
>> +
>> +	for_each_xfs_iext(ifp, &icur, &got) {
>> +		del = got;
>> +		if (isnullstartblock(got.br_startblock)) {
>> +			error = xfs_bmap_del_extent_delay(ip,
>> +					whichfork, &icur, &got, &del);
>> +			if (error)
>> +				goto out;
>> +		} else {
>> +			error = xfs_bmap_del_extent_real(ip, tp, &icur, dfops,
>> +					NULL, &del, &tmp_logflags, whichfork, 0);
>> +			if (error)
>> +				goto out;
>> +			*logflagsp |= tmp_logflags;
>> +		}
>> +	}
>> +init_local_fork:
>> +	kaddr = kmap_atomic(page);
>> +	xfs_init_local_fork(ip, whichfork, kaddr, isize);
>> +	kunmap_atomic(kaddr);
>> +	ip->i_d.di_format = XFS_DINODE_FMT_LOCAL;
>> +	XFS_IFORK_NEXT_SET(ip, whichfork, 0);
>> +	ip->i_d.di_size = isize;
>> +	*logflagsp |= (XFS_ILOG_DDATA | XFS_ILOG_CORE);
>> +out:
>> +	return error;
>> +}
>> +
>> +
>> +/*
>>    * Unmap (remove) blocks from a file.
>>    * If nexts is nonzero then the number of extents to remove is limited to
>>    * that value.  If not all extents in the block range can be removed then
>> diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h
>> index 9b49ddf99c41..22cd2642f1cd 100644
>> --- a/fs/xfs/libxfs/xfs_bmap.h
>> +++ b/fs/xfs/libxfs/xfs_bmap.h
>> @@ -271,6 +271,10 @@ int	xfs_bmap_map_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
>>   		struct xfs_inode *ip, struct xfs_bmbt_irec *imap);
>>   int	xfs_bmap_unmap_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
>>   		struct xfs_inode *ip, struct xfs_bmbt_irec *imap);
>> +int	xfs_bmap_extents_to_local(struct xfs_trans *tp, struct xfs_inode *ip,
>> +		struct xfs_defer_ops *dfops, int *flags, int whichfork,
>> +		struct page *page);
>> +void	xfs_bmap_forkoff_reset(struct xfs_inode *ip, int whichfork);
>>   
>>   static inline int xfs_bmap_fork_to_state(int whichfork)
>>   {
>> -- 
>> 2.11.0
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html

--
To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Christoph Hellwig July 8, 2018, 3:42 p.m. UTC | #3
>  /*
> + * Convert an inode from extents to the local format.
> + * Free all the extents of the inode and reset it to the local
> + * format. Copy the contents of the inode's blocks to the inode's
> + * literal area.
> + */

Please use up all 80 chars for your comments (and code)

> +int
> +xfs_bmap_extents_to_local(
> +	xfs_trans_t		*tp,
> +	xfs_inode_t		*ip,

Please use the struct types instead of the typedefs wherever possible.

> +	if (xfs_iext_count(ifp) == 0)
> +		goto init_local_fork;
> +
> +	for_each_xfs_iext(ifp, &icur, &got) {

for_each_xfs_iext should do the right thing for an empty fork.

> +out:
> +	return error;

Just return errors directly instead of going to a label that returns
the error.

> +}
> +
> +
> +/*

One blank line after a function body is enough.

--
To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Shan Hai July 9, 2018, 1:58 a.m. UTC | #4
On 2018年07月08日 23:42, Christoph Hellwig wrote:
>>   /*
>> + * Convert an inode from extents to the local format.
>> + * Free all the extents of the inode and reset it to the local
>> + * format. Copy the contents of the inode's blocks to the inode's
>> + * literal area.
>> + */
> Please use up all 80 chars for your comments (and code)
>
>> +int
>> +xfs_bmap_extents_to_local(
>> +	xfs_trans_t		*tp,
>> +	xfs_inode_t		*ip,
> Please use the struct types instead of the typedefs wherever possible.
>
>> +	if (xfs_iext_count(ifp) == 0)
>> +		goto init_local_fork;
>> +
>> +	for_each_xfs_iext(ifp, &icur, &got) {
> for_each_xfs_iext should do the right thing for an empty fork.
>
>> +out:
>> +	return error;
> Just return errors directly instead of going to a label that returns
> the error.
>
>> +}
>> +
>> +
>> +/*
> One blank line after a function body is enough.
>

OK, I will fix all of the above, thanks for the review.

Thanks
Shan Hai
--
To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index 7205268b30bc..bea6dc254a7d 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -1,6 +1,7 @@ 
 // SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (c) 2000-2006 Silicon Graphics, Inc.
+ * Copyright (c) 2018 Oracle.
  * All Rights Reserved.
  */
 #include "xfs.h"
@@ -213,7 +214,7 @@  xfs_default_attroffset(
  * attribute fork from local to extent format - we reset it where
  * possible to make space available for inline data fork extents.
  */
-STATIC void
+void
 xfs_bmap_forkoff_reset(
 	xfs_inode_t	*ip,
 	int		whichfork)
@@ -5141,6 +5142,63 @@  xfs_bmap_del_extent_real(
 }
 
 /*
+ * Convert an inode from extents to the local format.
+ * Free all the extents of the inode and reset it to the local
+ * format. Copy the contents of the inode's blocks to the inode's
+ * literal area.
+ */
+int
+xfs_bmap_extents_to_local(
+	xfs_trans_t		*tp,
+	xfs_inode_t		*ip,
+	struct xfs_defer_ops	*dfops,
+	int			*logflagsp,
+	int			whichfork,
+	struct page		*page)
+{
+	xfs_ifork_t		*ifp = XFS_IFORK_PTR(ip, whichfork);
+	xfs_fileoff_t		isize = i_size_read(VFS_I(ip));
+	struct xfs_bmbt_irec	got, del;
+	struct xfs_iext_cursor	icur;
+	int			error = 0;
+	int			tmp_logflags;
+	char			*kaddr = NULL;
+
+	ASSERT(whichfork != XFS_COW_FORK);
+	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS);
+
+	if (xfs_iext_count(ifp) == 0)
+		goto init_local_fork;
+
+	for_each_xfs_iext(ifp, &icur, &got) {
+		del = got;
+		if (isnullstartblock(got.br_startblock)) {
+			error = xfs_bmap_del_extent_delay(ip,
+					whichfork, &icur, &got, &del);
+			if (error)
+				goto out;
+		} else {
+			error = xfs_bmap_del_extent_real(ip, tp, &icur, dfops,
+					NULL, &del, &tmp_logflags, whichfork, 0);
+			if (error)
+				goto out;
+			*logflagsp |= tmp_logflags;
+		}
+	}
+init_local_fork:
+	kaddr = kmap_atomic(page);
+	xfs_init_local_fork(ip, whichfork, kaddr, isize);
+	kunmap_atomic(kaddr);
+	ip->i_d.di_format = XFS_DINODE_FMT_LOCAL;
+	XFS_IFORK_NEXT_SET(ip, whichfork, 0);
+	ip->i_d.di_size = isize;
+	*logflagsp |= (XFS_ILOG_DDATA | XFS_ILOG_CORE);
+out:
+	return error;
+}
+
+
+/*
  * Unmap (remove) blocks from a file.
  * If nexts is nonzero then the number of extents to remove is limited to
  * that value.  If not all extents in the block range can be removed then
diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h
index 9b49ddf99c41..22cd2642f1cd 100644
--- a/fs/xfs/libxfs/xfs_bmap.h
+++ b/fs/xfs/libxfs/xfs_bmap.h
@@ -271,6 +271,10 @@  int	xfs_bmap_map_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
 		struct xfs_inode *ip, struct xfs_bmbt_irec *imap);
 int	xfs_bmap_unmap_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
 		struct xfs_inode *ip, struct xfs_bmbt_irec *imap);
+int	xfs_bmap_extents_to_local(struct xfs_trans *tp, struct xfs_inode *ip,
+		struct xfs_defer_ops *dfops, int *flags, int whichfork,
+		struct page *page);
+void	xfs_bmap_forkoff_reset(struct xfs_inode *ip, int whichfork);
 
 static inline int xfs_bmap_fork_to_state(int whichfork)
 {