mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2025-01-27 10:24:22 +03:00
Calculate header size correctly in sa_find_sizes()
In the case where a variable-sized SA overlaps the spill block pointer and a new variable-sized SA is being added, the header size was improperly calculated to include the to-be-moved SA. This problem could be reproduced when xattr=sa enabled as follows: ln -s $(perl -e 'print "x" x 120') blah setfattr -n security.selinux -v blahblah -h blah The symlink is large enough to interfere with the spill block pointer and has a typical SA registration as follows (shown in modified "zdb -dddd" <SA attr layout obj> format): [ ... ZPL_DACL_COUNT ZPL_DACL_ACES ZPL_SYMLINK ] Adding the SA xattr will attempt to extend the registration to: [ ... ZPL_DACL_COUNT ZPL_DACL_ACES ZPL_SYMLINK ZPL_DXATTR ] but since the ZPL_SYMLINK SA interferes with the spill block pointer, it must also be moved to the spill block which will have a registration of: [ ZPL_SYMLINK ZPL_DXATTR ] This commit updates extra_hdrsize when this condition occurs, allowing hdrsize to be subsequently decreased appropriately. Signed-off-by: Tim Chase <tim@chase2k.com> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Ned Bass <bass6@llnl.gov> Issue #2214 Issue #2228 Issue #2316 Issue #2343
This commit is contained in:
parent
3937ab20f3
commit
83021b47c2
@ -594,7 +594,7 @@ sa_find_sizes(sa_os_t *sa, sa_bulk_attr_t *attr_desc, int attr_count,
|
|||||||
ASSERT(IS_P2ALIGNED(full_space, 8));
|
ASSERT(IS_P2ALIGNED(full_space, 8));
|
||||||
|
|
||||||
for (i = 0; i != attr_count; i++) {
|
for (i = 0; i != attr_count; i++) {
|
||||||
boolean_t is_var_sz;
|
boolean_t is_var_sz, might_spill_here;
|
||||||
|
|
||||||
*total = P2ROUNDUP(*total, 8);
|
*total = P2ROUNDUP(*total, 8);
|
||||||
*total += attr_desc[i].sa_length;
|
*total += attr_desc[i].sa_length;
|
||||||
@ -606,6 +606,11 @@ sa_find_sizes(sa_os_t *sa, sa_bulk_attr_t *attr_desc, int attr_count,
|
|||||||
var_size++;
|
var_size++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
might_spill_here =
|
||||||
|
buftype == SA_BONUS && *index == -1 &&
|
||||||
|
(*total + P2ROUNDUP(hdrsize, 8)) >
|
||||||
|
(full_space - sizeof (blkptr_t));
|
||||||
|
|
||||||
if (is_var_sz && var_size > 1) {
|
if (is_var_sz && var_size > 1) {
|
||||||
/*
|
/*
|
||||||
* Don't worry that the spill block might overflow.
|
* Don't worry that the spill block might overflow.
|
||||||
@ -622,7 +627,7 @@ sa_find_sizes(sa_os_t *sa, sa_bulk_attr_t *attr_desc, int attr_count,
|
|||||||
* spill-over.
|
* spill-over.
|
||||||
*/
|
*/
|
||||||
hdrsize += sizeof (uint16_t);
|
hdrsize += sizeof (uint16_t);
|
||||||
if (*index != -1)
|
if (*index != -1 || might_spill_here)
|
||||||
extra_hdrsize += sizeof (uint16_t);
|
extra_hdrsize += sizeof (uint16_t);
|
||||||
} else {
|
} else {
|
||||||
ASSERT(buftype == SA_BONUS);
|
ASSERT(buftype == SA_BONUS);
|
||||||
@ -639,11 +644,8 @@ sa_find_sizes(sa_os_t *sa, sa_bulk_attr_t *attr_desc, int attr_count,
|
|||||||
* space. The sum is used later for sizing bonus
|
* space. The sum is used later for sizing bonus
|
||||||
* and spill buffer.
|
* and spill buffer.
|
||||||
*/
|
*/
|
||||||
if (buftype == SA_BONUS && *index == -1 &&
|
if (might_spill_here)
|
||||||
(*total + P2ROUNDUP(hdrsize, 8)) >
|
|
||||||
(full_space - sizeof (blkptr_t))) {
|
|
||||||
*index = i;
|
*index = i;
|
||||||
}
|
|
||||||
|
|
||||||
if ((*total + P2ROUNDUP(hdrsize, 8)) > full_space &&
|
if ((*total + P2ROUNDUP(hdrsize, 8)) > full_space &&
|
||||||
buftype == SA_BONUS)
|
buftype == SA_BONUS)
|
||||||
|
Loading…
Reference in New Issue
Block a user