From: Brian Foster <bfoster@redhat.com>
To: xfs@oss.sgi.com
Subject: [PATCH 2/2] xfs: use larger in-core attr firstused field and detect overflow
Date: Tue, 24 Feb 2015 15:50:24 -0500 [thread overview]
Message-ID: <1424811024-24839-3-git-send-email-bfoster@redhat.com> (raw)
In-Reply-To: <1424811024-24839-1-git-send-email-bfoster@redhat.com>
The on-disk xfs_attr3_leaf_hdr structure firstused field is 16-bit and
subject to overflow when fs block size is 64k. The field is typically
initialized to block size when an attr leaf block is initialized. This
problem is demonstrated by assert failures when running xfstests
generic/117 on an fs with 64k blocks.
To support the existing attr leaf block algorithms for insertion,
rebalance and entry movement, increase the size of the in-core firstused
field to 32-bit and handle the potential overflow on conversion to/from
the on-disk structure. If the overflow condition occurs, set a special
value in the firstused field that is translated back on header read. The
special value is only required in the case of an empty 64k attr block. A
value of zero is used because firstused is initialized to the block size
and grows backwards from there. Furthermore, the attribute block header
occupies the first bytes of the block. Thus, a value of zero has no
other legitimate meaning for this structure.
Signed-off-by: Brian Foster <bfoster@redhat.com>
---
fs/xfs/libxfs/xfs_attr_leaf.c | 36 +++++++++++++++++++++++++++++++++---
fs/xfs/libxfs/xfs_da_format.h | 8 +++++++-
2 files changed, 40 insertions(+), 4 deletions(-)
diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c
index 3337516..3277b40 100644
--- a/fs/xfs/libxfs/xfs_attr_leaf.c
+++ b/fs/xfs/libxfs/xfs_attr_leaf.c
@@ -106,6 +106,12 @@ xfs_attr3_leaf_hdr_from_disk(
to->count = be16_to_cpu(hdr3->count);
to->usedbytes = be16_to_cpu(hdr3->usedbytes);
to->firstused = be16_to_cpu(hdr3->firstused);
+ if (to->firstused == XFS_ATTR3_LEAF_NULLOFF) {
+ /* only empty blocks when size overflows firstused! */
+ ASSERT(!to->count && !to->usedbytes &&
+ geo->blksize > USHRT_MAX);
+ to->firstused = geo->blksize;
+ }
to->holes = hdr3->holes;
for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) {
@@ -120,6 +126,12 @@ xfs_attr3_leaf_hdr_from_disk(
to->count = be16_to_cpu(from->hdr.count);
to->usedbytes = be16_to_cpu(from->hdr.usedbytes);
to->firstused = be16_to_cpu(from->hdr.firstused);
+ if (to->firstused == XFS_ATTR3_LEAF_NULLOFF) {
+ /* only empty blocks when size overflows firstused! */
+ ASSERT(!to->count && !to->usedbytes &&
+ geo->blksize > USHRT_MAX);
+ to->firstused = geo->blksize;
+ }
to->holes = from->hdr.holes;
for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) {
@@ -134,11 +146,29 @@ xfs_attr3_leaf_hdr_to_disk(
struct xfs_attr_leafblock *to,
struct xfs_attr3_icleaf_hdr *from)
{
- int i;
+ int i;
+ uint16_t firstused;
ASSERT(from->magic == XFS_ATTR_LEAF_MAGIC ||
from->magic == XFS_ATTR3_LEAF_MAGIC);
+ /*
+ * Handle overflow of the on-disk firstused field. firstused is
+ * typically initialized to block size, but we only have 2-bytes in the
+ * on-disk structure. This means a 64k block size overflows the field.
+ *
+ * firstused should only match block size for an empty attr block so set
+ * a special value that the from_disk() variant can convert back to
+ * blocksize in the in-core structure.
+ */
+ if (from->firstused > USHRT_MAX) {
+ ASSERT(from->firstused == geo->blksize);
+ firstused = XFS_ATTR3_LEAF_NULLOFF;
+ } else {
+ ASSERT(from->firstused != 0);
+ firstused = from->firstused;
+ }
+
if (from->magic == XFS_ATTR3_LEAF_MAGIC) {
struct xfs_attr3_leaf_hdr *hdr3 = (struct xfs_attr3_leaf_hdr *)to;
@@ -147,7 +177,7 @@ xfs_attr3_leaf_hdr_to_disk(
hdr3->info.hdr.magic = cpu_to_be16(from->magic);
hdr3->count = cpu_to_be16(from->count);
hdr3->usedbytes = cpu_to_be16(from->usedbytes);
- hdr3->firstused = cpu_to_be16(from->firstused);
+ hdr3->firstused = cpu_to_be16(firstused);
hdr3->holes = from->holes;
hdr3->pad1 = 0;
@@ -162,7 +192,7 @@ xfs_attr3_leaf_hdr_to_disk(
to->hdr.info.magic = cpu_to_be16(from->magic);
to->hdr.count = cpu_to_be16(from->count);
to->hdr.usedbytes = cpu_to_be16(from->usedbytes);
- to->hdr.firstused = cpu_to_be16(from->firstused);
+ to->hdr.firstused = cpu_to_be16(firstused);
to->hdr.holes = from->holes;
to->hdr.pad1 = 0;
diff --git a/fs/xfs/libxfs/xfs_da_format.h b/fs/xfs/libxfs/xfs_da_format.h
index 0a49b02..d2d0498 100644
--- a/fs/xfs/libxfs/xfs_da_format.h
+++ b/fs/xfs/libxfs/xfs_da_format.h
@@ -725,7 +725,7 @@ struct xfs_attr3_icleaf_hdr {
__uint16_t magic;
__uint16_t count;
__uint16_t usedbytes;
- __uint16_t firstused;
+ __uint32_t firstused;
__u8 holes;
struct {
__uint16_t base;
@@ -734,6 +734,12 @@ struct xfs_attr3_icleaf_hdr {
};
/*
+ * Special value to represent fs block size in the leaf header firstused field.
+ * Only used when block size overflows the 2-bytes available on disk.
+ */
+#define XFS_ATTR3_LEAF_NULLOFF 0
+
+/*
* Flags used in the leaf_entry[i].flags field.
* NOTE: the INCOMPLETE bit must not collide with the flags bits specified
* on the system call, they are "or"ed together for various operations.
--
1.9.3
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
next prev parent reply other threads:[~2015-02-24 20:50 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-02-24 20:50 [PATCH 0/2] xfs: avoid overflow of attr3 leaf block headers with 64k blocks Brian Foster
2015-02-24 20:50 ` [PATCH 1/2] xfs: pass attr geometry to attr leaf header conversion functions Brian Foster
2015-03-25 20:51 ` Dave Chinner
2015-02-24 20:50 ` Brian Foster [this message]
2015-03-25 21:04 ` [PATCH 2/2] xfs: use larger in-core attr firstused field and detect overflow Dave Chinner
2015-03-25 16:56 ` [PATCH 0/2] xfs: avoid overflow of attr3 leaf block headers with 64k blocks Brian Foster
2015-03-25 17:59 ` Darrick J. Wong
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1424811024-24839-3-git-send-email-bfoster@redhat.com \
--to=bfoster@redhat.com \
--cc=xfs@oss.sgi.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox