From: Alexey Lyashkov Date: Fri, 9 Oct 2015 06:23:47 +0000 (-0600) Subject: LU-7261 ldiskfs: fix large_xattr overwrite X-Git-Tag: 2.7.62~4 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=66ca2bc59135b00cd20a4e5095a23cf54cdfa2eb LU-7261 ldiskfs: fix large_xattr overwrite Handle the case where a large (external inode) xattr is being replaced correctly. The special case for this in ext4_set_xattr() was incorrectly setting the offset of the xattr data within the inode when it shouldn't have. Add an e2fsck check of the large_xattr filesystem in conf-sanity test_61 to verify this is working correctly. Signed-off-by: Alexey Lyashkov Signed-off-by: Andreas Dilger Change-Id: I27123d7985eff0538b6f64139cebc2f0f1806260 Reviewed-on: http://review.whamcloud.com/16777 Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Jian Yu Reviewed-by: Niu Yawei Reviewed-by: Oleg Drokin --- diff --git a/ldiskfs/kernel_patches/patches/rhel6.3/ext4-large-eas.patch b/ldiskfs/kernel_patches/patches/rhel6.3/ext4-large-eas.patch index 5981307..142fec2 100644 --- a/ldiskfs/kernel_patches/patches/rhel6.3/ext4-large-eas.patch +++ b/ldiskfs/kernel_patches/patches/rhel6.3/ext4-large-eas.patch @@ -471,13 +471,13 @@ Index: linux-stage/fs/ext4/xattr.c void *first_val = s->base + min_offs; size_t offs = le16_to_cpu(s->here->e_value_offs); void *val = s->base + offs; -@@ -606,13 +884,17 @@ ext4_xattr_set_entry(struct ext4_xattr_i +@@ -606,13 +884,18 @@ ext4_xattr_set_entry(struct ext4_xattr_i last = s->first; while (!IS_LAST_ENTRY(last)) { size_t o = le16_to_cpu(last->e_value_offs); - if (!last->e_value_block && -- last->e_value_size && o < offs) -+ if (last->e_value_size > 0 && o < offs) ++ if (!last->e_value_inum && + last->e_value_size && o < offs) last->e_value_offs = cpu_to_le16(o + size); last = EXT4_XATTR_NEXT(last); diff --git a/ldiskfs/kernel_patches/patches/rhel7/ext4-large-eas.patch b/ldiskfs/kernel_patches/patches/rhel7/ext4-large-eas.patch index 1fd34aa..b7251db 100644 --- a/ldiskfs/kernel_patches/patches/rhel7/ext4-large-eas.patch +++ b/ldiskfs/kernel_patches/patches/rhel7/ext4-large-eas.patch @@ -568,13 +568,13 @@ Index: linux-stage/fs/ext4/xattr.c void *first_val = s->base + min_offs; size_t offs = le16_to_cpu(s->here->e_value_offs); void *val = s->base + offs; -@@ -685,13 +966,17 @@ ext4_xattr_set_entry(struct ext4_xattr_i +@@ -685,13 +966,18 @@ ext4_xattr_set_entry(struct ext4_xattr_i last = s->first; while (!IS_LAST_ENTRY(last)) { size_t o = le16_to_cpu(last->e_value_offs); - if (!last->e_value_block && -- last->e_value_size && o < offs) -+ if (last->e_value_size > 0 && o < offs) ++ if (!last->e_value_inum && + last->e_value_size && o < offs) last->e_value_offs = cpu_to_le16(o + size); last = EXT4_XATTR_NEXT(last); diff --git a/ldiskfs/kernel_patches/patches/sles11sp2/ext4-large-eas.patch b/ldiskfs/kernel_patches/patches/sles11sp2/ext4-large-eas.patch index 57e5f90..ba0e281 100644 --- a/ldiskfs/kernel_patches/patches/sles11sp2/ext4-large-eas.patch +++ b/ldiskfs/kernel_patches/patches/sles11sp2/ext4-large-eas.patch @@ -575,13 +575,13 @@ Index: linux-stage/fs/ext4/xattr.c void *first_val = s->base + min_offs; size_t offs = le16_to_cpu(s->here->e_value_offs); void *val = s->base + offs; -@@ -607,13 +888,17 @@ ext4_xattr_set_entry(struct ext4_xattr_i +@@ -607,13 +888,18 @@ ext4_xattr_set_entry(struct ext4_xattr_i last = s->first; while (!IS_LAST_ENTRY(last)) { size_t o = le16_to_cpu(last->e_value_offs); - if (!last->e_value_block && -- last->e_value_size && o < offs) -+ if (last->e_value_size > 0 && o < offs) ++ if (!last->e_value_inum && + last->e_value_size && o < offs) last->e_value_offs = cpu_to_le16(o + size); last = EXT4_XATTR_NEXT(last); diff --git a/ldiskfs/kernel_patches/patches/sles12/ext4-large-eas.patch b/ldiskfs/kernel_patches/patches/sles12/ext4-large-eas.patch index d596093..8ff7f93 100644 --- a/ldiskfs/kernel_patches/patches/sles12/ext4-large-eas.patch +++ b/ldiskfs/kernel_patches/patches/sles12/ext4-large-eas.patch @@ -558,13 +558,13 @@ Index: linux-stage/fs/ext4/xattr.c void *first_val = s->base + min_offs; size_t offs = le16_to_cpu(s->here->e_value_offs); void *val = s->base + offs; -@@ -680,13 +958,17 @@ ext4_xattr_set_entry(struct ext4_xattr_i +@@ -680,13 +958,18 @@ ext4_xattr_set_entry(struct ext4_xattr_i last = s->first; while (!IS_LAST_ENTRY(last)) { size_t o = le16_to_cpu(last->e_value_offs); - if (!last->e_value_block && -- last->e_value_size && o < offs) -+ if (last->e_value_size > 0 && o < offs) ++ if (!last->e_value_inum && + last->e_value_size && o < offs) last->e_value_offs = cpu_to_le16(o + size); last = EXT4_XATTR_NEXT(last); diff --git a/lustre/tests/conf-sanity.sh b/lustre/tests/conf-sanity.sh index eeef083..492a32f 100644 --- a/lustre/tests/conf-sanity.sh +++ b/lustre/tests/conf-sanity.sh @@ -4108,42 +4108,53 @@ test_61() { # LU-80 local large_value="$(generate_string $(max_xattr_size))" local small_value="bar" - local name="trusted.big" - log "save large xattr $name on $file" - setfattr -n $name -v $large_value $file || - error "saving $name on $file failed" - - local new_value=$(get_xattr_value $name $file) - [[ "$new_value" != "$large_value" ]] && - error "$name different after saving" - - log "shrink value of $name on $file" - setfattr -n $name -v $small_value $file || - error "shrinking value of $name on $file failed" - - new_value=$(get_xattr_value $name $file) - [[ "$new_value" != "$small_value" ]] && - error "$name different after shrinking" - - log "grow value of $name on $file" - setfattr -n $name -v $large_value $file || - error "growing value of $name on $file failed" - - new_value=$(get_xattr_value $name $file) - [[ "$new_value" != "$large_value" ]] && - error "$name different after growing" - - log "check value of $name on $file after remounting MDS" - fail $SINGLEMDS - new_value=$(get_xattr_value $name $file) - [[ "$new_value" != "$large_value" ]] && - error "$name different after remounting MDS" - - log "remove large xattr $name from $file" - setfattr -x $name $file || error "removing $name from $file failed" - - rm -f $file - stopall + local name="trusted.big" + log "save large xattr $name on $file" + setfattr -n $name -v $large_value $file || + error "saving $name on $file failed" + + local new_value=$(get_xattr_value $name $file) + [[ "$new_value" != "$large_value" ]] && + error "$name different after saving" + + log "shrink value of $name on $file" + setfattr -n $name -v $small_value $file || + error "shrinking value of $name on $file failed" + + new_value=$(get_xattr_value $name $file) + [[ "$new_value" != "$small_value" ]] && + error "$name different after shrinking" + + log "grow value of $name on $file" + setfattr -n $name -v $large_value $file || + error "growing value of $name on $file failed" + + new_value=$(get_xattr_value $name $file) + [[ "$new_value" != "$large_value" ]] && + error "$name different after growing" + + log "check value of $name on $file after remounting MDS" + fail $SINGLEMDS + new_value=$(get_xattr_value $name $file) + [[ "$new_value" != "$large_value" ]] && + error "$name different after remounting MDS" + + log "remove large xattr $name from $file" + setfattr -x $name $file || error "removing $name from $file failed" + + if $lxattr; then + stopall || error "stopping for e2fsck run" + for num in $(seq $MDSCOUNT); do + run_e2fsck $(facet_active_host mds$num) \ + $(mdsdevname $num) "-y" || + error "e2fsck MDT$num failed" + done + setup_noconfig || error "remounting the filesystem failed" + fi + + # need to delete this file to avoid problems in other tests + rm -f $file + stopall || error "stopping systems to turn off large_xattr" if $lxattr; then for num in $(seq $MDSCOUNT); do do_facet mds${num} $TUNE2FS -O ^large_xattr \