Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preserve itx alloc size for zio_data_buf_free() #6912

Merged
merged 1 commit into from
Dec 4, 2017

Conversation

behlendorf
Copy link
Contributor

Description

Using zio_data_buf_alloc() to allocate the itx's may be unsafe
because the itx->itx_lr.lrc_reclen field is not constant from
allocation to free. This size is used by zio_data_buf_free() to
determine which cache the object should be returned to, a change
in size may result in the wrong cache being selected.

Avoid this issue entirely by storing the allocation size in the
itx as itx->itx_size. Additionally, switch to using vmem_alloc()
to perform the allocation. For the vast majority of allocations
which are <64k this will internally map to kmem_alloc() and will
therefore not impact performance.

Motivation and Context

Potential issue identified by inspection while testing #6566.

How Has This Been Tested?

$ ./scripts/zfs-tests.sh -vx -T slog
...
Test: tests/functional/slog/setup (run as root) [00:01] [PASS]
Test: tests/functional/slog/slog_001_pos (run as root) [00:45] [PASS]
Test: tests/functional/slog/slog_002_pos (run as root) [00:48] [PASS]
Test: tests/functional/slog/slog_003_pos (run as root) [01:42] [PASS]
Test: tests/functional/slog/slog_004_pos (run as root) [00:50] [PASS]
Test: tests/functional/slog/slog_005_pos (run as root) [00:24] [PASS]
Test: tests/functional/slog/slog_006_pos (run as root) [04:48] [PASS]
Test: tests/functional/slog/slog_007_pos (run as root) [01:56] [PASS]
Test: tests/functional/slog/slog_008_neg (run as root) [00:03] [PASS]
Test: tests/functional/slog/slog_009_neg (run as root) [00:13] [PASS]
Test: tests/functional/slog/slog_010_neg (run as root) [00:01] [PASS]
Test: tests/functional/slog/slog_011_neg (run as root) [00:44] [PASS]
Test: tests/functional/slog/slog_012_neg (run as root) [00:44] [PASS]
Test: tests/functional/slog/slog_013_pos (run as root) [00:00] [SKIP]
Test: tests/functional/slog/slog_014_pos (run as root) [01:34] [PASS]
Test: tests/functional/slog/slog_replay_fs (run as root) [00:14] [PASS]
Test: tests/functional/slog/slog_replay_volume (run as root) [00:21] [PASS]
Test: tests/functional/slog/cleanup (run as root) [00:01] [PASS]

Results Summary
SKIP	   1
PASS	  17

Submitted PR for a full run of the ZTS.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Performance enhancement (non-breaking change which improves efficiency)
  • Code cleanup (non-breaking change which makes code smaller or more readable)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation (a change to man pages or other documentation)

Checklist:

  • My code follows the ZFS on Linux code style requirements.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.
  • All commit messages are properly formatted and contain Signed-off-by.
  • Change has been approved by a ZFS on Linux member.

Copy link
Member

@prakashsurya prakashsurya left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

Can you also comment a little more about the motivation to move back to using vmem_alloc. Since we moved from vmem_alloc to zio_data_buf_alloc, and now we're going back to vmem_alloc, I think it'd be good to explain why we're not regressing on commit 19ea3d2 by doing this.

Additionally, we should port this to openzfs right? At least, the portion adding itx_size to the itx_t structure.

@@ -395,6 +395,7 @@ typedef struct itx {
uint8_t itx_sync; /* synchronous transaction */
zil_callback_t itx_callback; /* Called when the itx is persistent */
void *itx_callback_data; /* User data for the callback */
size_t itx_size; /* itx size including lr.lrc_reclen */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the comment here seems a little sketchy to me, since if lr.lrc_reclen changes, we won't modify itx_size to match this comment. it might be better to state this field is used to ensure we properly free the itx_t structure, since that's really the reason the field exists, right? with the comment as is, I might interpret the fact we don't modify this field when changing lr.lrc_reclen as a bug, when that's not the case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, right this simply needs to exist because kmem_free() requires the size. Passing a different value for the size will only result in an ASSERT when DEBUG_KMEM_TRACKING is defined. I'll change it to,

	size_t		itx_size;	/* allocated itx struct size */

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 great, thanks!

@behlendorf
Copy link
Contributor Author

Can you also comment a little more about the motivation to move back to using vmem_alloc.

Will do, I'll expand further on the why this is OK in the commit message comment.

Additionally, we should port this to openzfs right?

Yes, we probably should port the itx->itx_size portion to ensure that alloc/free match. I'm not sure what, if any, consequences there are in OpenZFS if these differ.

@behlendorf behlendorf changed the title Use vmem_alloc for itx_t allocations Preserve itx alloc size for zio_data_buf_free() Dec 1, 2017
Using zio_data_buf_alloc() to allocate the itx's may be unsafe
because the itx->itx_lr.lrc_reclen field is not constant from
allocation to free.  Using a different itx->itx_lr.lrc_reclen
size in zio_data_buf_free() can result in the allocation being
returned to the wrong kmem cache.

This issue can be avoided entirely by storing the allocation size
in itx->itx_size and using that for zio_data_buf_free().

Signed-off-by: Brian Behlendorf <[email protected]>
@behlendorf
Copy link
Contributor Author

@prakashsurya refreshed. I've reconsidered the vmem_alloc() change. There's no compelling need to switch to a different allocator now that the size is preserved correctly and risk potentially reintroducing the issues addressed by 19ea3d2.

@codecov
Copy link

codecov bot commented Dec 2, 2017

Codecov Report

Merging #6912 into master will increase coverage by 0.02%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff            @@
##           master   #6912      +/-   ##
=========================================
+ Coverage   75.18%   75.2%   +0.02%     
=========================================
  Files         296     296              
  Lines       95197   95199       +2     
=========================================
+ Hits        71577   71598      +21     
+ Misses      23620   23601      -19
Flag Coverage Δ
#kernel 74.5% <100%> (-0.02%) ⬇️
#user 67.41% <100%> (-0.16%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update d467726...13effb3. Read the comment docs.

@openzfs openzfs deleted a comment from codecov bot Dec 4, 2017
@openzfs openzfs deleted a comment from codecov bot Dec 4, 2017
@behlendorf behlendorf merged commit 72841b9 into openzfs:master Dec 4, 2017
tonyhutter pushed a commit that referenced this pull request Dec 5, 2017
Using zio_data_buf_alloc() to allocate the itx's may be unsafe
because the itx->itx_lr.lrc_reclen field is not constant from
allocation to free.  Using a different itx->itx_lr.lrc_reclen
size in zio_data_buf_free() can result in the allocation being
returned to the wrong kmem cache.

This issue can be avoided entirely by storing the allocation size
in itx->itx_size and using that for zio_data_buf_free().

Reviewed by: Prakash Surya <[email protected]>
Signed-off-by: Brian Behlendorf <[email protected]>
Closes #6912
tonyhutter pushed a commit to tonyhutter/zfs that referenced this pull request Dec 5, 2017
Using zio_data_buf_alloc() to allocate the itx's may be unsafe
because the itx->itx_lr.lrc_reclen field is not constant from
allocation to free.  Using a different itx->itx_lr.lrc_reclen
size in zio_data_buf_free() can result in the allocation being
returned to the wrong kmem cache.

This issue can be avoided entirely by storing the allocation size
in itx->itx_size and using that for zio_data_buf_free().

Reviewed by: Prakash Surya <[email protected]>
Signed-off-by: Brian Behlendorf <[email protected]>
Closes openzfs#6912
Nasf-Fan pushed a commit to Nasf-Fan/zfs that referenced this pull request Jan 29, 2018
Using zio_data_buf_alloc() to allocate the itx's may be unsafe
because the itx->itx_lr.lrc_reclen field is not constant from
allocation to free.  Using a different itx->itx_lr.lrc_reclen
size in zio_data_buf_free() can result in the allocation being
returned to the wrong kmem cache.

This issue can be avoided entirely by storing the allocation size
in itx->itx_size and using that for zio_data_buf_free().

Reviewed by: Prakash Surya <[email protected]>
Signed-off-by: Brian Behlendorf <[email protected]>
Closes openzfs#6912
Nasf-Fan pushed a commit to Nasf-Fan/zfs that referenced this pull request Feb 13, 2018
Using zio_data_buf_alloc() to allocate the itx's may be unsafe
because the itx->itx_lr.lrc_reclen field is not constant from
allocation to free.  Using a different itx->itx_lr.lrc_reclen
size in zio_data_buf_free() can result in the allocation being
returned to the wrong kmem cache.

This issue can be avoided entirely by storing the allocation size
in itx->itx_size and using that for zio_data_buf_free().

Reviewed by: Prakash Surya <[email protected]>
Signed-off-by: Brian Behlendorf <[email protected]>
Closes openzfs#6912
@behlendorf behlendorf deleted the zil-itx-alloc branch April 19, 2021 19:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants