All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] f2fs: avoid race in between read xattr & write xattr
@ 2017-09-05  9:42 Yunlei He
  2017-09-05 12:08 ` Chao Yu
  0 siblings, 1 reply; 2+ messages in thread
From: Yunlei He @ 2017-09-05  9:42 UTC (permalink / raw)
  To: jaegeuk, yuchao0, linux-f2fs-devel; +Cc: heyunlei, morgan.wang

Thread A:					Thread B:
-f2fs_getxattr
   -lookup_all_xattrs
      -xnid = F2FS_I(inode)->i_xattr_nid;
						-f2fs_setxattr
						    -__f2fs_setxattr
						        -write_all_xattrs
						            -truncate_xattr_node
							          ...  ...
						-write_checkpoint
								  ...  ...
						-alloc_nid   <- nid reuse
          -get_node_page
              -f2fs_bug_on  <- nid != node_footer->nid

It's need a rw_sem to avoid the race

Signed-off-by: Yunlei He <heyunlei@huawei.com>
---
 fs/f2fs/f2fs.h  | 1 +
 fs/f2fs/super.c | 1 +
 fs/f2fs/xattr.c | 6 ++++++
 3 files changed, 8 insertions(+)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 4b99396..e99c1fe 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -589,6 +589,7 @@ struct f2fs_inode_info {
 	struct extent_tree *extent_tree;	/* cached extent_tree entry */
 	struct rw_semaphore dio_rwsem[2];/* avoid racing between dio and gc */
 	struct rw_semaphore i_mmap_sem;
+	struct rw_semaphore xattr_sem;
 
 	int i_extra_isize;		/* size of extra space located in i_addr */
 	kprojid_t i_projid;		/* id for project quota */
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 7730316..03950eb 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -630,6 +630,7 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb)
 	init_rwsem(&fi->dio_rwsem[READ]);
 	init_rwsem(&fi->dio_rwsem[WRITE]);
 	init_rwsem(&fi->i_mmap_sem);
+	init_rwsem(&fi->xattr_sem);
 
 #ifdef CONFIG_QUOTA
 	memset(&fi->i_dquot, 0, sizeof(fi->i_dquot));
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c
index ef3a372..590fe3a 100644
--- a/fs/f2fs/xattr.c
+++ b/fs/f2fs/xattr.c
@@ -503,7 +503,9 @@ ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
 	int error = 0;
 	size_t rest = buffer_size;
 
+	down_read(&F2FS_I(inode)->xattr_sem);
 	error = read_all_xattrs(inode, NULL, &base_addr);
+	up_read(&F2FS_I(inode)->xattr_sem);
 	if (error)
 		return error;
 
@@ -573,7 +575,9 @@ static int __f2fs_setxattr(struct inode *inode, int index,
 	if (size > MAX_VALUE_LEN(inode))
 		return -E2BIG;
 
+	down_read(&F2FS_I(inode)->xattr_sem);
 	error = read_all_xattrs(inode, ipage, &base_addr);
+	up_read(&F2FS_I(inode)->xattr_sem);
 	if (error)
 		return error;
 
@@ -650,7 +654,9 @@ static int __f2fs_setxattr(struct inode *inode, int index,
 		new_hsize += newsize;
 	}
 
+	down_write(&F2FS_I(inode)->xattr_sem);
 	error = write_all_xattrs(inode, new_hsize, base_addr, ipage);
+	up_write(&F2FS_I(inode)->xattr_sem);
 	if (error)
 		goto exit;
 
-- 
1.9.1


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH] f2fs: avoid race in between read xattr & write xattr
  2017-09-05  9:42 [PATCH] f2fs: avoid race in between read xattr & write xattr Yunlei He
@ 2017-09-05 12:08 ` Chao Yu
  0 siblings, 0 replies; 2+ messages in thread
From: Chao Yu @ 2017-09-05 12:08 UTC (permalink / raw)
  To: Yunlei He, jaegeuk, yuchao0, linux-f2fs-devel; +Cc: morgan.wang

On 2017/9/5 17:42, Yunlei He wrote:
> Thread A:					Thread B:
> -f2fs_getxattr
>    -lookup_all_xattrs
>       -xnid = F2FS_I(inode)->i_xattr_nid;
> 						-f2fs_setxattr
> 						    -__f2fs_setxattr
> 						        -write_all_xattrs
> 						            -truncate_xattr_node
> 							          ...  ...
> 						-write_checkpoint
> 								  ...  ...
> 						-alloc_nid   <- nid reuse
>           -get_node_page
>               -f2fs_bug_on  <- nid != node_footer->nid
> 
> It's need a rw_sem to avoid the race
> 
> Signed-off-by: Yunlei He <heyunlei@huawei.com>
> ---
>  fs/f2fs/f2fs.h  | 1 +
>  fs/f2fs/super.c | 1 +
>  fs/f2fs/xattr.c | 6 ++++++
>  3 files changed, 8 insertions(+)
> 
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index 4b99396..e99c1fe 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -589,6 +589,7 @@ struct f2fs_inode_info {
>  	struct extent_tree *extent_tree;	/* cached extent_tree entry */
>  	struct rw_semaphore dio_rwsem[2];/* avoid racing between dio and gc */
>  	struct rw_semaphore i_mmap_sem;
> +	struct rw_semaphore xattr_sem;

i_xattr_sem;	/* avoid racing between reading and changing EAs */

>  
>  	int i_extra_isize;		/* size of extra space located in i_addr */
>  	kprojid_t i_projid;		/* id for project quota */
> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> index 7730316..03950eb 100644
> --- a/fs/f2fs/super.c
> +++ b/fs/f2fs/super.c
> @@ -630,6 +630,7 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb)
>  	init_rwsem(&fi->dio_rwsem[READ]);
>  	init_rwsem(&fi->dio_rwsem[WRITE]);
>  	init_rwsem(&fi->i_mmap_sem);
> +	init_rwsem(&fi->xattr_sem);
>  
>  #ifdef CONFIG_QUOTA
>  	memset(&fi->i_dquot, 0, sizeof(fi->i_dquot));
> diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c
> index ef3a372..590fe3a 100644
> --- a/fs/f2fs/xattr.c
> +++ b/fs/f2fs/xattr.c
> @@ -503,7 +503,9 @@ ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
>  	int error = 0;
>  	size_t rest = buffer_size;
>  
> +	down_read(&F2FS_I(inode)->xattr_sem);
>  	error = read_all_xattrs(inode, NULL, &base_addr);
> +	up_read(&F2FS_I(inode)->xattr_sem);
>  	if (error)
>  		return error;
>  
> @@ -573,7 +575,9 @@ static int __f2fs_setxattr(struct inode *inode, int index,
>  	if (size > MAX_VALUE_LEN(inode))
>  		return -E2BIG;
>  
> +	down_read(&F2FS_I(inode)->xattr_sem);
>  	error = read_all_xattrs(inode, ipage, &base_addr);
> +	up_read(&F2FS_I(inode)->xattr_sem);
>  	if (error)
>  		return error;
>  
> @@ -650,7 +654,9 @@ static int __f2fs_setxattr(struct inode *inode, int index,
>  		new_hsize += newsize;
>  	}
>  
> +	down_write(&F2FS_I(inode)->xattr_sem);
>  	error = write_all_xattrs(inode, new_hsize, base_addr, ipage);
> +	up_write(&F2FS_I(inode)->xattr_sem);

How about avoiding gap between read_all_xattrs and write_all_xattrs in __f2fs_setxattr?

Also needs to cover lookup_all_xattrs.

Thanks,

>  	if (error)
>  		goto exit;
>  
> 

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2017-09-05 12:08 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-09-05  9:42 [PATCH] f2fs: avoid race in between read xattr & write xattr Yunlei He
2017-09-05 12:08 ` Chao Yu

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.