diff mbox

[10/22] btrfs: alloc space cache inode with GFP_NOFS

Message ID 20180719145006.17532-10-josef@toxicpanda.com (mailing list archive)
State New, archived
Headers show

Commit Message

Josef Bacik July 19, 2018, 2:49 p.m. UTC
If we're allocating a new space cache inode it's likely going to be
under a transaction handle, so we need to use GFP_NOFS to keep from
deadlocking.  Otherwise GFP_KERNEL is fine.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/free-space-cache.c | 5 +++++
 fs/btrfs/inode.c            | 3 ++-
 fs/btrfs/transaction.h      | 1 +
 3 files changed, 8 insertions(+), 1 deletion(-)

Comments

Nikolay Borisov July 19, 2018, 3:35 p.m. UTC | #1
On 19.07.2018 17:49, Josef Bacik wrote:
> If we're allocating a new space cache inode it's likely going to be
> under a transaction handle, so we need to use GFP_NOFS to keep from
> deadlocking.  Otherwise GFP_KERNEL is fine.
> 
> Signed-off-by: Josef Bacik <josef@toxicpanda.com>
> ---
>  fs/btrfs/free-space-cache.c | 5 +++++
>  fs/btrfs/inode.c            | 3 ++-
>  fs/btrfs/transaction.h      | 1 +
>  3 files changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
> index d5f80cb300be..13bc514e4e16 100644
> --- a/fs/btrfs/free-space-cache.c
> +++ b/fs/btrfs/free-space-cache.c
> @@ -68,7 +68,12 @@ static struct inode *__lookup_free_space_inode(struct btrfs_root *root,
>  	btrfs_disk_key_to_cpu(&location, &disk_key);
>  	btrfs_release_path(path);
>  
> +	/* We need this set so that we use GFP_NOFS when allocating our inode. */
> +	if (current->journal_info == NULL)
> +		current->journal_info = BTRFS_TRANS_STUB;
>  	inode = btrfs_iget(fs_info->sb, &location, root, NULL);
> +	if (current->journal_info == BTRFS_TRANS_STUB)
> +		current->journal_info = NULL;
This is not safe in the face of stacked filesystem, i.e ext4 uses the
journal_info.

>  	if (IS_ERR(inode))
>  		return inode;
>  	if (is_bad_inode(inode)) {
> diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
> index eba61bcb9bb3..14ecfe5d6110 100644
> --- a/fs/btrfs/inode.c
> +++ b/fs/btrfs/inode.c
> @@ -9211,8 +9211,9 @@ struct inode *btrfs_alloc_inode(struct super_block *sb)
>  	struct btrfs_fs_info *fs_info = btrfs_sb(sb);
>  	struct btrfs_inode *ei;
>  	struct inode *inode;
> +	gfp_t flags = (current->journal_info) ? GFP_NOFS : GFP_KERNEL;
>  
> -	ei = kmem_cache_alloc(btrfs_inode_cachep, GFP_KERNEL);
> +	ei = kmem_cache_alloc(btrfs_inode_cachep, flags);

Why don't you just hardcode GFP_NOFS? We should be striving at removing
abuse of ->journal_info than proliferating it.

>  	if (!ei)
>  		return NULL;
>  
> diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h
> index 94439482a0ec..172ff923bf15 100644
> --- a/fs/btrfs/transaction.h
> +++ b/fs/btrfs/transaction.h
> @@ -106,6 +106,7 @@ struct btrfs_transaction {
>  #define TRANS_EXTWRITERS	(__TRANS_START | __TRANS_ATTACH)
>  
>  #define BTRFS_SEND_TRANS_STUB	((void *)1)
> +#define BTRFS_TRANS_STUB	((void *)2)
>  
>  struct btrfs_trans_handle {
>  	u64 transid;
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Sterba July 19, 2018, 3:44 p.m. UTC | #2
On Thu, Jul 19, 2018 at 06:35:33PM +0300, Nikolay Borisov wrote:
> 
> 
> On 19.07.2018 17:49, Josef Bacik wrote:
> > If we're allocating a new space cache inode it's likely going to be
> > under a transaction handle, so we need to use GFP_NOFS to keep from
> > deadlocking.  Otherwise GFP_KERNEL is fine.
> > 
> > Signed-off-by: Josef Bacik <josef@toxicpanda.com>
> > ---
> >  fs/btrfs/free-space-cache.c | 5 +++++
> >  fs/btrfs/inode.c            | 3 ++-
> >  fs/btrfs/transaction.h      | 1 +
> >  3 files changed, 8 insertions(+), 1 deletion(-)
> > 
> > diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
> > index d5f80cb300be..13bc514e4e16 100644
> > --- a/fs/btrfs/free-space-cache.c
> > +++ b/fs/btrfs/free-space-cache.c
> > @@ -68,7 +68,12 @@ static struct inode *__lookup_free_space_inode(struct btrfs_root *root,
> >  	btrfs_disk_key_to_cpu(&location, &disk_key);
> >  	btrfs_release_path(path);
> >  
> > +	/* We need this set so that we use GFP_NOFS when allocating our inode. */
> > +	if (current->journal_info == NULL)
> > +		current->journal_info = BTRFS_TRANS_STUB;
> >  	inode = btrfs_iget(fs_info->sb, &location, root, NULL);
> > +	if (current->journal_info == BTRFS_TRANS_STUB)
> > +		current->journal_info = NULL;
> This is not safe in the face of stacked filesystem, i.e ext4 uses the
> journal_info.
> 
> >  	if (IS_ERR(inode))
> >  		return inode;
> >  	if (is_bad_inode(inode)) {
> > diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
> > index eba61bcb9bb3..14ecfe5d6110 100644
> > --- a/fs/btrfs/inode.c
> > +++ b/fs/btrfs/inode.c
> > @@ -9211,8 +9211,9 @@ struct inode *btrfs_alloc_inode(struct super_block *sb)
> >  	struct btrfs_fs_info *fs_info = btrfs_sb(sb);
> >  	struct btrfs_inode *ei;
> >  	struct inode *inode;
> > +	gfp_t flags = (current->journal_info) ? GFP_NOFS : GFP_KERNEL;
> >  
> > -	ei = kmem_cache_alloc(btrfs_inode_cachep, GFP_KERNEL);
> > +	ei = kmem_cache_alloc(btrfs_inode_cachep, flags);
> 
> Why don't you just hardcode GFP_NOFS? We should be striving at removing
> abuse of ->journal_info than proliferating it.

We're also removing unnecessary use of GFP_NOFS. The right way here is
to use memalloc_nofs_save/memalloc_nofs_restore around btrfs_iget.
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Josef Bacik July 19, 2018, 3:55 p.m. UTC | #3
On Thu, Jul 19, 2018 at 06:35:33PM +0300, Nikolay Borisov wrote:
> 
> 
> On 19.07.2018 17:49, Josef Bacik wrote:
> > If we're allocating a new space cache inode it's likely going to be
> > under a transaction handle, so we need to use GFP_NOFS to keep from
> > deadlocking.  Otherwise GFP_KERNEL is fine.
> > 
> > Signed-off-by: Josef Bacik <josef@toxicpanda.com>
> > ---
> >  fs/btrfs/free-space-cache.c | 5 +++++
> >  fs/btrfs/inode.c            | 3 ++-
> >  fs/btrfs/transaction.h      | 1 +
> >  3 files changed, 8 insertions(+), 1 deletion(-)
> > 
> > diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
> > index d5f80cb300be..13bc514e4e16 100644
> > --- a/fs/btrfs/free-space-cache.c
> > +++ b/fs/btrfs/free-space-cache.c
> > @@ -68,7 +68,12 @@ static struct inode *__lookup_free_space_inode(struct btrfs_root *root,
> >  	btrfs_disk_key_to_cpu(&location, &disk_key);
> >  	btrfs_release_path(path);
> >  
> > +	/* We need this set so that we use GFP_NOFS when allocating our inode. */
> > +	if (current->journal_info == NULL)
> > +		current->journal_info = BTRFS_TRANS_STUB;
> >  	inode = btrfs_iget(fs_info->sb, &location, root, NULL);
> > +	if (current->journal_info == BTRFS_TRANS_STUB)
> > +		current->journal_info = NULL;
> This is not safe in the face of stacked filesystem, i.e ext4 uses the
> journal_info.

Stacked file systems arent safe at all because we all use journal_info, this
doesn't change that.

> 
> >  	if (IS_ERR(inode))
> >  		return inode;
> >  	if (is_bad_inode(inode)) {
> > diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
> > index eba61bcb9bb3..14ecfe5d6110 100644
> > --- a/fs/btrfs/inode.c
> > +++ b/fs/btrfs/inode.c
> > @@ -9211,8 +9211,9 @@ struct inode *btrfs_alloc_inode(struct super_block *sb)
> >  	struct btrfs_fs_info *fs_info = btrfs_sb(sb);
> >  	struct btrfs_inode *ei;
> >  	struct inode *inode;
> > +	gfp_t flags = (current->journal_info) ? GFP_NOFS : GFP_KERNEL;
> >  
> > -	ei = kmem_cache_alloc(btrfs_inode_cachep, GFP_KERNEL);
> > +	ei = kmem_cache_alloc(btrfs_inode_cachep, flags);
> 
> Why don't you just hardcode GFP_NOFS? We should be striving at removing
> abuse of ->journal_info than proliferating it.
> 

Because every time I use GFP_NOFS some mm guy shows up and complains.  I'm fine
with doing GFP_NOFS, but the vast majority of allocations are in paths that
GFP_KERNEL is fine.  Thanks,

Josef
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Josef Bacik July 19, 2018, 3:56 p.m. UTC | #4
On Thu, Jul 19, 2018 at 05:44:53PM +0200, David Sterba wrote:
> On Thu, Jul 19, 2018 at 06:35:33PM +0300, Nikolay Borisov wrote:
> > 
> > 
> > On 19.07.2018 17:49, Josef Bacik wrote:
> > > If we're allocating a new space cache inode it's likely going to be
> > > under a transaction handle, so we need to use GFP_NOFS to keep from
> > > deadlocking.  Otherwise GFP_KERNEL is fine.
> > > 
> > > Signed-off-by: Josef Bacik <josef@toxicpanda.com>
> > > ---
> > >  fs/btrfs/free-space-cache.c | 5 +++++
> > >  fs/btrfs/inode.c            | 3 ++-
> > >  fs/btrfs/transaction.h      | 1 +
> > >  3 files changed, 8 insertions(+), 1 deletion(-)
> > > 
> > > diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
> > > index d5f80cb300be..13bc514e4e16 100644
> > > --- a/fs/btrfs/free-space-cache.c
> > > +++ b/fs/btrfs/free-space-cache.c
> > > @@ -68,7 +68,12 @@ static struct inode *__lookup_free_space_inode(struct btrfs_root *root,
> > >  	btrfs_disk_key_to_cpu(&location, &disk_key);
> > >  	btrfs_release_path(path);
> > >  
> > > +	/* We need this set so that we use GFP_NOFS when allocating our inode. */
> > > +	if (current->journal_info == NULL)
> > > +		current->journal_info = BTRFS_TRANS_STUB;
> > >  	inode = btrfs_iget(fs_info->sb, &location, root, NULL);
> > > +	if (current->journal_info == BTRFS_TRANS_STUB)
> > > +		current->journal_info = NULL;
> > This is not safe in the face of stacked filesystem, i.e ext4 uses the
> > journal_info.
> > 
> > >  	if (IS_ERR(inode))
> > >  		return inode;
> > >  	if (is_bad_inode(inode)) {
> > > diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
> > > index eba61bcb9bb3..14ecfe5d6110 100644
> > > --- a/fs/btrfs/inode.c
> > > +++ b/fs/btrfs/inode.c
> > > @@ -9211,8 +9211,9 @@ struct inode *btrfs_alloc_inode(struct super_block *sb)
> > >  	struct btrfs_fs_info *fs_info = btrfs_sb(sb);
> > >  	struct btrfs_inode *ei;
> > >  	struct inode *inode;
> > > +	gfp_t flags = (current->journal_info) ? GFP_NOFS : GFP_KERNEL;
> > >  
> > > -	ei = kmem_cache_alloc(btrfs_inode_cachep, GFP_KERNEL);
> > > +	ei = kmem_cache_alloc(btrfs_inode_cachep, flags);
> > 
> > Why don't you just hardcode GFP_NOFS? We should be striving at removing
> > abuse of ->journal_info than proliferating it.
> 
> We're also removing unnecessary use of GFP_NOFS. The right way here is
> to use memalloc_nofs_save/memalloc_nofs_restore around btrfs_iget.

Huh I didn't know this existed, that's neat.  I'll change this patch to do that,
thanks,

Josef
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" 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/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
index d5f80cb300be..13bc514e4e16 100644
--- a/fs/btrfs/free-space-cache.c
+++ b/fs/btrfs/free-space-cache.c
@@ -68,7 +68,12 @@  static struct inode *__lookup_free_space_inode(struct btrfs_root *root,
 	btrfs_disk_key_to_cpu(&location, &disk_key);
 	btrfs_release_path(path);
 
+	/* We need this set so that we use GFP_NOFS when allocating our inode. */
+	if (current->journal_info == NULL)
+		current->journal_info = BTRFS_TRANS_STUB;
 	inode = btrfs_iget(fs_info->sb, &location, root, NULL);
+	if (current->journal_info == BTRFS_TRANS_STUB)
+		current->journal_info = NULL;
 	if (IS_ERR(inode))
 		return inode;
 	if (is_bad_inode(inode)) {
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index eba61bcb9bb3..14ecfe5d6110 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -9211,8 +9211,9 @@  struct inode *btrfs_alloc_inode(struct super_block *sb)
 	struct btrfs_fs_info *fs_info = btrfs_sb(sb);
 	struct btrfs_inode *ei;
 	struct inode *inode;
+	gfp_t flags = (current->journal_info) ? GFP_NOFS : GFP_KERNEL;
 
-	ei = kmem_cache_alloc(btrfs_inode_cachep, GFP_KERNEL);
+	ei = kmem_cache_alloc(btrfs_inode_cachep, flags);
 	if (!ei)
 		return NULL;
 
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h
index 94439482a0ec..172ff923bf15 100644
--- a/fs/btrfs/transaction.h
+++ b/fs/btrfs/transaction.h
@@ -106,6 +106,7 @@  struct btrfs_transaction {
 #define TRANS_EXTWRITERS	(__TRANS_START | __TRANS_ATTACH)
 
 #define BTRFS_SEND_TRANS_STUB	((void *)1)
+#define BTRFS_TRANS_STUB	((void *)2)
 
 struct btrfs_trans_handle {
 	u64 transid;