linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* re: btrfs: add tracing for failed reservations
@ 2015-11-10  9:08 Dan Carpenter
  2015-11-10 13:55 ` Jeff Mahoney
  0 siblings, 1 reply; 3+ messages in thread
From: Dan Carpenter @ 2015-11-10  9:08 UTC (permalink / raw)
  To: jeffm; +Cc: linux-btrfs

[ This is old.  I don't know why it's only complaining now. Anyway this
  looks like one of those rarely used code paths so it might be a real
  bug. ]

Hello Jeff Mahoney,

The patch cab45e22da48: "btrfs: add tracing for failed reservations"
from Oct 16, 2013, leads to the following static checker warning:

	fs/btrfs/extent-tree.c:4116 btrfs_alloc_data_chunk_ondemand()
	error: we previously assumed 'data_sinfo' could be null (see line 4016)

fs/btrfs/extent-tree.c
  4014  
  4015          data_sinfo = fs_info->data_sinfo;
  4016          if (!data_sinfo)
                    ^^^^^^^^^^^
Check for NULL.

  4017                  goto alloc;
  4018  
  4019  again:
  4020          /* make sure we have enough space to handle the data first */
  4021          spin_lock(&data_sinfo->lock);
  4022          used = data_sinfo->bytes_used + data_sinfo->bytes_reserved +
  4023                  data_sinfo->bytes_pinned + data_sinfo->bytes_readonly +
  4024                  data_sinfo->bytes_may_use;
  4025  
  4026          if (used + bytes > data_sinfo->total_bytes) {
  4027                  struct btrfs_trans_handle *trans;
  4028  
  4029                  /*
  4030                   * if we don't have enough free bytes in this space then we need
  4031                   * to alloc a new chunk.
  4032                   */
  4033                  if (!data_sinfo->full) {
  4034                          u64 alloc_target;
  4035  
  4036                          data_sinfo->force_alloc = CHUNK_ALLOC_FORCE;
  4037                          spin_unlock(&data_sinfo->lock);
  4038  alloc:

We jump to here.

  4039                          alloc_target = btrfs_get_alloc_profile(root, 1);
  4040                          /*
  4041                           * It is ugly that we don't call nolock join
  4042                           * transaction for the free space inode case here.
  4043                           * But it is safe because we only do the data space
  4044                           * reservation for the free space cache in the
  4045                           * transaction context, the common join transaction
  4046                           * just increase the counter of the current transaction
  4047                           * handler, doesn't try to acquire the trans_lock of
  4048                           * the fs.
  4049                           */
  4050                          trans = btrfs_join_transaction(root);
  4051                          if (IS_ERR(trans))
  4052                                  return PTR_ERR(trans);
  4053  
  4054                          ret = do_chunk_alloc(trans, root->fs_info->extent_root,
  4055                                               alloc_target,
  4056                                               CHUNK_ALLOC_NO_FORCE);
  4057                          btrfs_end_transaction(trans, root);
  4058                          if (ret < 0) {
  4059                                  if (ret != -ENOSPC)
  4060                                          return ret;
  4061                                  else {
  4062                                          have_pinned_space = 1;
  4063                                          goto commit_trans;

The btrfs_end_transaction() call fails.

  4064                                  }
  4065                          }
  4066  
  4067                          if (!data_sinfo)
  4068                                  data_sinfo = fs_info->data_sinfo;
  4069  
  4070                          goto again;
  4071                  }
  4072  
  4073                  /*
  4074                   * If we don't have enough pinned space to deal with this
  4075                   * allocation, and no removed chunk in current transaction,
  4076                   * don't bother committing the transaction.
  4077                   */
  4078                  have_pinned_space = percpu_counter_compare(
  4079                          &data_sinfo->total_bytes_pinned,
  4080                          used + bytes - data_sinfo->total_bytes);
  4081                  spin_unlock(&data_sinfo->lock);
  4082  
  4083                  /* commit the current transaction and try again */
  4084  commit_trans:

We jump to here.

  4085                  if (need_commit &&
  4086                      !atomic_read(&root->fs_info->open_ioctl_trans)) {
  4087                          need_commit--;
  4088  
  4089                          if (need_commit > 0)
  4090                                  btrfs_wait_ordered_roots(fs_info, -1);
  4091  
  4092                          trans = btrfs_join_transaction(root);
  4093                          if (IS_ERR(trans))
  4094                                  return PTR_ERR(trans);
  4095                          if (have_pinned_space >= 0 ||
  4096                              test_bit(BTRFS_TRANS_HAVE_FREE_BGS,
  4097                                       &trans->transaction->flags) ||
  4098                              need_commit > 0) {
  4099                                  ret = btrfs_commit_transaction(trans, root);
  4100                                  if (ret)
  4101                                          return ret;
  4102                                  /*
  4103                                   * make sure that all running delayed iput are
  4104                                   * done
  4105                                   */
  4106                                  down_write(&root->fs_info->delayed_iput_sem);
  4107                                  up_write(&root->fs_info->delayed_iput_sem);
  4108                                  goto again;
  4109                          } else {
  4110                                  btrfs_end_transaction(trans, root);
  4111                          }
  4112                  }
  4113  
  4114                  trace_btrfs_space_reservation(root->fs_info,
  4115                                                "space_info:enospc",
  4116                                                data_sinfo->flags, bytes, 1);
                                                      ^^^^^^^^^^^^^^^^^
Potential NULL deref.

  4117                  return -ENOSPC;

regards,
dan carpenter

^ permalink raw reply	[flat|nested] 3+ messages in thread
* re: btrfs: add tracing for failed reservations
@ 2013-11-13 20:01 Dan Carpenter
  0 siblings, 0 replies; 3+ messages in thread
From: Dan Carpenter @ 2013-11-13 20:01 UTC (permalink / raw)
  To: jeffm; +Cc: linux-btrfs

Hello Jeff Mahoney,

This is a semi-automatic email about new static checker warnings.

The patch cab45e22da48: "btrfs: add tracing for failed reservations" 
from Oct 16, 2013, leads to the following Smatch complaint:

fs/btrfs/extent-tree.c:3710 btrfs_check_data_free_space()
	 error: we previously assumed 'data_sinfo' could be null (see line 3629)

fs/btrfs/extent-tree.c
  3628		data_sinfo = fs_info->data_sinfo;
  3629		if (!data_sinfo)
                    ^^^^^^^^^^^
Existing check.

  3630			goto alloc;
  3631	
  3632	again:
  3633		/* make sure we have enough space to handle the data first */
  3634		spin_lock(&data_sinfo->lock);
  3635		used = data_sinfo->bytes_used + data_sinfo->bytes_reserved +
  3636			data_sinfo->bytes_pinned + data_sinfo->bytes_readonly +
  3637			data_sinfo->bytes_may_use;
  3638	
  3639		if (used + bytes > data_sinfo->total_bytes) {
  3640			struct btrfs_trans_handle *trans;
  3641	
  3642			/*
  3643			 * if we don't have enough free bytes in this space then we need
  3644			 * to alloc a new chunk.
  3645			 */
  3646			if (!data_sinfo->full && alloc_chunk) {
  3647				u64 alloc_target;
  3648	
  3649				data_sinfo->force_alloc = CHUNK_ALLOC_FORCE;
  3650				spin_unlock(&data_sinfo->lock);
  3651	alloc:
  3652				alloc_target = btrfs_get_alloc_profile(root, 1);
  3653				/*
  3654				 * It is ugly that we don't call nolock join
  3655				 * transaction for the free space inode case here.
  3656				 * But it is safe because we only do the data space
  3657				 * reservation for the free space cache in the
  3658				 * transaction context, the common join transaction
  3659				 * just increase the counter of the current transaction
  3660				 * handler, doesn't try to acquire the trans_lock of
  3661				 * the fs.
  3662				 */
  3663				trans = btrfs_join_transaction(root);
  3664				if (IS_ERR(trans))
  3665					return PTR_ERR(trans);
  3666	
  3667				ret = do_chunk_alloc(trans, root->fs_info->extent_root,
  3668						     alloc_target,
  3669						     CHUNK_ALLOC_NO_FORCE);
  3670				btrfs_end_transaction(trans, root);
  3671				if (ret < 0) {
  3672					if (ret != -ENOSPC)
  3673						return ret;
  3674					else
  3675						goto commit_trans;
                                                ^^^^^^^^^^^^^^^^^
Imagine we hit this goto and data_sinfo is NULL.

  3676				}
  3677	
  3678				if (!data_sinfo)
  3679					data_sinfo = fs_info->data_sinfo;
  3680	
  3681				goto again;
  3682			}
  3683	
  3684			/*
  3685			 * If we don't have enough pinned space to deal with this
  3686			 * allocation don't bother committing the transaction.
  3687			 */
  3688			if (percpu_counter_compare(&data_sinfo->total_bytes_pinned,
  3689						   bytes) < 0)
  3690				committed = 1;
  3691			spin_unlock(&data_sinfo->lock);
  3692	
  3693			/* commit the current transaction and try again */
  3694	commit_trans:
  3695			if (!committed &&
  3696			    !atomic_read(&root->fs_info->open_ioctl_trans)) {
  3697				committed = 1;
  3698	
  3699				trans = btrfs_join_transaction(root);
  3700				if (IS_ERR(trans))
  3701					return PTR_ERR(trans);
  3702				ret = btrfs_commit_transaction(trans, root);
  3703				if (ret)
  3704					return ret;
  3705				goto again;
  3706			}
  3707	
  3708			trace_btrfs_space_reservation(root->fs_info,
  3709						      "space_info:enospc",
  3710						      data_sinfo->flags, bytes, 1);
                                                      ^^^^^^^^^^^^^^^^^
Patch introduces an unchecked dereference.

  3711			return -ENOSPC;
  3712		}

regards,
dan carpenter

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

end of thread, other threads:[~2015-11-10 13:56 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-11-10  9:08 btrfs: add tracing for failed reservations Dan Carpenter
2015-11-10 13:55 ` Jeff Mahoney
  -- strict thread matches above, loose matches on Subject: below --
2013-11-13 20:01 Dan Carpenter

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).