Commit 6a63ef06 authored by Dave Chinner's avatar Dave Chinner

Merge branch 'xfs-misc-fixes-for-4.1-3' into for-next

Conflicts:
	fs/xfs/xfs_iops.c
parents a448f8f1 21c3ea18
...@@ -86,8 +86,83 @@ STATIC void xfs_attr3_leaf_moveents(struct xfs_da_args *args, ...@@ -86,8 +86,83 @@ STATIC void xfs_attr3_leaf_moveents(struct xfs_da_args *args,
int move_count); int move_count);
STATIC int xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index); STATIC int xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index);
/*
* attr3 block 'firstused' conversion helpers.
*
* firstused refers to the offset of the first used byte of the nameval region
* of an attr leaf block. The region starts at the tail of the block and expands
* backwards towards the middle. As such, firstused is initialized to the block
* size for an empty leaf block and is reduced from there.
*
* The attr3 block size is pegged to the fsb size and the maximum fsb is 64k.
* The in-core firstused field is 32-bit and thus supports the maximum fsb size.
* The on-disk field is only 16-bit, however, and overflows at 64k. Since this
* only occurs at exactly 64k, we use zero as a magic on-disk value to represent
* the attr block size. The following helpers manage the conversion between the
* in-core and on-disk formats.
*/
static void
xfs_attr3_leaf_firstused_from_disk(
struct xfs_da_geometry *geo,
struct xfs_attr3_icleaf_hdr *to,
struct xfs_attr_leafblock *from)
{
struct xfs_attr3_leaf_hdr *hdr3;
if (from->hdr.info.magic == cpu_to_be16(XFS_ATTR3_LEAF_MAGIC)) {
hdr3 = (struct xfs_attr3_leaf_hdr *) from;
to->firstused = be16_to_cpu(hdr3->firstused);
} else {
to->firstused = be16_to_cpu(from->hdr.firstused);
}
/*
* Convert from the magic fsb size value to actual blocksize. This
* should only occur for empty blocks when the block size overflows
* 16-bits.
*/
if (to->firstused == XFS_ATTR3_LEAF_NULLOFF) {
ASSERT(!to->count && !to->usedbytes);
ASSERT(geo->blksize > USHRT_MAX);
to->firstused = geo->blksize;
}
}
static void
xfs_attr3_leaf_firstused_to_disk(
struct xfs_da_geometry *geo,
struct xfs_attr_leafblock *to,
struct xfs_attr3_icleaf_hdr *from)
{
struct xfs_attr3_leaf_hdr *hdr3;
uint32_t firstused;
/* magic value should only be seen on disk */
ASSERT(from->firstused != XFS_ATTR3_LEAF_NULLOFF);
/*
* Scale down the 32-bit in-core firstused value to the 16-bit on-disk
* value. This only overflows at the max supported value of 64k. Use the
* magic on-disk value to represent block size in this case.
*/
firstused = from->firstused;
if (firstused > USHRT_MAX) {
ASSERT(from->firstused == geo->blksize);
firstused = XFS_ATTR3_LEAF_NULLOFF;
}
if (from->magic == XFS_ATTR3_LEAF_MAGIC) {
hdr3 = (struct xfs_attr3_leaf_hdr *) to;
hdr3->firstused = cpu_to_be16(firstused);
} else {
to->hdr.firstused = cpu_to_be16(firstused);
}
}
void void
xfs_attr3_leaf_hdr_from_disk( xfs_attr3_leaf_hdr_from_disk(
struct xfs_da_geometry *geo,
struct xfs_attr3_icleaf_hdr *to, struct xfs_attr3_icleaf_hdr *to,
struct xfs_attr_leafblock *from) struct xfs_attr_leafblock *from)
{ {
...@@ -104,7 +179,7 @@ xfs_attr3_leaf_hdr_from_disk( ...@@ -104,7 +179,7 @@ xfs_attr3_leaf_hdr_from_disk(
to->magic = be16_to_cpu(hdr3->info.hdr.magic); to->magic = be16_to_cpu(hdr3->info.hdr.magic);
to->count = be16_to_cpu(hdr3->count); to->count = be16_to_cpu(hdr3->count);
to->usedbytes = be16_to_cpu(hdr3->usedbytes); to->usedbytes = be16_to_cpu(hdr3->usedbytes);
to->firstused = be16_to_cpu(hdr3->firstused); xfs_attr3_leaf_firstused_from_disk(geo, to, from);
to->holes = hdr3->holes; to->holes = hdr3->holes;
for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) { for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) {
...@@ -118,7 +193,7 @@ xfs_attr3_leaf_hdr_from_disk( ...@@ -118,7 +193,7 @@ xfs_attr3_leaf_hdr_from_disk(
to->magic = be16_to_cpu(from->hdr.info.magic); to->magic = be16_to_cpu(from->hdr.info.magic);
to->count = be16_to_cpu(from->hdr.count); to->count = be16_to_cpu(from->hdr.count);
to->usedbytes = be16_to_cpu(from->hdr.usedbytes); to->usedbytes = be16_to_cpu(from->hdr.usedbytes);
to->firstused = be16_to_cpu(from->hdr.firstused); xfs_attr3_leaf_firstused_from_disk(geo, to, from);
to->holes = from->hdr.holes; to->holes = from->hdr.holes;
for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) { for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) {
...@@ -129,6 +204,7 @@ xfs_attr3_leaf_hdr_from_disk( ...@@ -129,6 +204,7 @@ xfs_attr3_leaf_hdr_from_disk(
void void
xfs_attr3_leaf_hdr_to_disk( xfs_attr3_leaf_hdr_to_disk(
struct xfs_da_geometry *geo,
struct xfs_attr_leafblock *to, struct xfs_attr_leafblock *to,
struct xfs_attr3_icleaf_hdr *from) struct xfs_attr3_icleaf_hdr *from)
{ {
...@@ -145,7 +221,7 @@ xfs_attr3_leaf_hdr_to_disk( ...@@ -145,7 +221,7 @@ xfs_attr3_leaf_hdr_to_disk(
hdr3->info.hdr.magic = cpu_to_be16(from->magic); hdr3->info.hdr.magic = cpu_to_be16(from->magic);
hdr3->count = cpu_to_be16(from->count); hdr3->count = cpu_to_be16(from->count);
hdr3->usedbytes = cpu_to_be16(from->usedbytes); hdr3->usedbytes = cpu_to_be16(from->usedbytes);
hdr3->firstused = cpu_to_be16(from->firstused); xfs_attr3_leaf_firstused_to_disk(geo, to, from);
hdr3->holes = from->holes; hdr3->holes = from->holes;
hdr3->pad1 = 0; hdr3->pad1 = 0;
...@@ -160,7 +236,7 @@ xfs_attr3_leaf_hdr_to_disk( ...@@ -160,7 +236,7 @@ xfs_attr3_leaf_hdr_to_disk(
to->hdr.info.magic = cpu_to_be16(from->magic); to->hdr.info.magic = cpu_to_be16(from->magic);
to->hdr.count = cpu_to_be16(from->count); to->hdr.count = cpu_to_be16(from->count);
to->hdr.usedbytes = cpu_to_be16(from->usedbytes); to->hdr.usedbytes = cpu_to_be16(from->usedbytes);
to->hdr.firstused = cpu_to_be16(from->firstused); xfs_attr3_leaf_firstused_to_disk(geo, to, from);
to->hdr.holes = from->holes; to->hdr.holes = from->holes;
to->hdr.pad1 = 0; to->hdr.pad1 = 0;
...@@ -178,7 +254,7 @@ xfs_attr3_leaf_verify( ...@@ -178,7 +254,7 @@ xfs_attr3_leaf_verify(
struct xfs_attr_leafblock *leaf = bp->b_addr; struct xfs_attr_leafblock *leaf = bp->b_addr;
struct xfs_attr3_icleaf_hdr ichdr; struct xfs_attr3_icleaf_hdr ichdr;
xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf); xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &ichdr, leaf);
if (xfs_sb_version_hascrc(&mp->m_sb)) { if (xfs_sb_version_hascrc(&mp->m_sb)) {
struct xfs_da3_node_hdr *hdr3 = bp->b_addr; struct xfs_da3_node_hdr *hdr3 = bp->b_addr;
...@@ -757,9 +833,10 @@ xfs_attr_shortform_allfit( ...@@ -757,9 +833,10 @@ xfs_attr_shortform_allfit(
struct xfs_attr3_icleaf_hdr leafhdr; struct xfs_attr3_icleaf_hdr leafhdr;
int bytes; int bytes;
int i; int i;
struct xfs_mount *mp = bp->b_target->bt_mount;
leaf = bp->b_addr; leaf = bp->b_addr;
xfs_attr3_leaf_hdr_from_disk(&leafhdr, leaf); xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &leafhdr, leaf);
entry = xfs_attr3_leaf_entryp(leaf); entry = xfs_attr3_leaf_entryp(leaf);
bytes = sizeof(struct xfs_attr_sf_hdr); bytes = sizeof(struct xfs_attr_sf_hdr);
...@@ -812,7 +889,7 @@ xfs_attr3_leaf_to_shortform( ...@@ -812,7 +889,7 @@ xfs_attr3_leaf_to_shortform(
memcpy(tmpbuffer, bp->b_addr, args->geo->blksize); memcpy(tmpbuffer, bp->b_addr, args->geo->blksize);
leaf = (xfs_attr_leafblock_t *)tmpbuffer; leaf = (xfs_attr_leafblock_t *)tmpbuffer;
xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf); xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr, leaf);
entry = xfs_attr3_leaf_entryp(leaf); entry = xfs_attr3_leaf_entryp(leaf);
/* XXX (dgc): buffer is about to be marked stale - why zero it? */ /* XXX (dgc): buffer is about to be marked stale - why zero it? */
...@@ -923,7 +1000,7 @@ xfs_attr3_leaf_to_node( ...@@ -923,7 +1000,7 @@ xfs_attr3_leaf_to_node(
btree = dp->d_ops->node_tree_p(node); btree = dp->d_ops->node_tree_p(node);
leaf = bp2->b_addr; leaf = bp2->b_addr;
xfs_attr3_leaf_hdr_from_disk(&icleafhdr, leaf); xfs_attr3_leaf_hdr_from_disk(args->geo, &icleafhdr, leaf);
entries = xfs_attr3_leaf_entryp(leaf); entries = xfs_attr3_leaf_entryp(leaf);
/* both on-disk, don't endian-flip twice */ /* both on-disk, don't endian-flip twice */
...@@ -988,7 +1065,7 @@ xfs_attr3_leaf_create( ...@@ -988,7 +1065,7 @@ xfs_attr3_leaf_create(
} }
ichdr.freemap[0].size = ichdr.firstused - ichdr.freemap[0].base; ichdr.freemap[0].size = ichdr.firstused - ichdr.freemap[0].base;
xfs_attr3_leaf_hdr_to_disk(leaf, &ichdr); xfs_attr3_leaf_hdr_to_disk(args->geo, leaf, &ichdr);
xfs_trans_log_buf(args->trans, bp, 0, args->geo->blksize - 1); xfs_trans_log_buf(args->trans, bp, 0, args->geo->blksize - 1);
*bpp = bp; *bpp = bp;
...@@ -1073,7 +1150,7 @@ xfs_attr3_leaf_add( ...@@ -1073,7 +1150,7 @@ xfs_attr3_leaf_add(
trace_xfs_attr_leaf_add(args); trace_xfs_attr_leaf_add(args);
leaf = bp->b_addr; leaf = bp->b_addr;
xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf); xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr, leaf);
ASSERT(args->index >= 0 && args->index <= ichdr.count); ASSERT(args->index >= 0 && args->index <= ichdr.count);
entsize = xfs_attr_leaf_newentsize(args, NULL); entsize = xfs_attr_leaf_newentsize(args, NULL);
...@@ -1126,7 +1203,7 @@ xfs_attr3_leaf_add( ...@@ -1126,7 +1203,7 @@ xfs_attr3_leaf_add(
tmp = xfs_attr3_leaf_add_work(bp, &ichdr, args, 0); tmp = xfs_attr3_leaf_add_work(bp, &ichdr, args, 0);
out_log_hdr: out_log_hdr:
xfs_attr3_leaf_hdr_to_disk(leaf, &ichdr); xfs_attr3_leaf_hdr_to_disk(args->geo, leaf, &ichdr);
xfs_trans_log_buf(args->trans, bp, xfs_trans_log_buf(args->trans, bp,
XFS_DA_LOGRANGE(leaf, &leaf->hdr, XFS_DA_LOGRANGE(leaf, &leaf->hdr,
xfs_attr3_leaf_hdr_size(leaf))); xfs_attr3_leaf_hdr_size(leaf)));
...@@ -1294,7 +1371,7 @@ xfs_attr3_leaf_compact( ...@@ -1294,7 +1371,7 @@ xfs_attr3_leaf_compact(
ichdr_dst->freemap[0].base; ichdr_dst->freemap[0].base;
/* write the header back to initialise the underlying buffer */ /* write the header back to initialise the underlying buffer */
xfs_attr3_leaf_hdr_to_disk(leaf_dst, ichdr_dst); xfs_attr3_leaf_hdr_to_disk(args->geo, leaf_dst, ichdr_dst);
/* /*
* Copy all entry's in the same (sorted) order, * Copy all entry's in the same (sorted) order,
...@@ -1344,9 +1421,10 @@ xfs_attr_leaf_order( ...@@ -1344,9 +1421,10 @@ xfs_attr_leaf_order(
{ {
struct xfs_attr3_icleaf_hdr ichdr1; struct xfs_attr3_icleaf_hdr ichdr1;
struct xfs_attr3_icleaf_hdr ichdr2; struct xfs_attr3_icleaf_hdr ichdr2;
struct xfs_mount *mp = leaf1_bp->b_target->bt_mount;
xfs_attr3_leaf_hdr_from_disk(&ichdr1, leaf1_bp->b_addr); xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &ichdr1, leaf1_bp->b_addr);
xfs_attr3_leaf_hdr_from_disk(&ichdr2, leaf2_bp->b_addr); xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &ichdr2, leaf2_bp->b_addr);
return xfs_attr3_leaf_order(leaf1_bp, &ichdr1, leaf2_bp, &ichdr2); return xfs_attr3_leaf_order(leaf1_bp, &ichdr1, leaf2_bp, &ichdr2);
} }
...@@ -1388,8 +1466,8 @@ xfs_attr3_leaf_rebalance( ...@@ -1388,8 +1466,8 @@ xfs_attr3_leaf_rebalance(
ASSERT(blk2->magic == XFS_ATTR_LEAF_MAGIC); ASSERT(blk2->magic == XFS_ATTR_LEAF_MAGIC);
leaf1 = blk1->bp->b_addr; leaf1 = blk1->bp->b_addr;
leaf2 = blk2->bp->b_addr; leaf2 = blk2->bp->b_addr;
xfs_attr3_leaf_hdr_from_disk(&ichdr1, leaf1); xfs_attr3_leaf_hdr_from_disk(state->args->geo, &ichdr1, leaf1);
xfs_attr3_leaf_hdr_from_disk(&ichdr2, leaf2); xfs_attr3_leaf_hdr_from_disk(state->args->geo, &ichdr2, leaf2);
ASSERT(ichdr2.count == 0); ASSERT(ichdr2.count == 0);
args = state->args; args = state->args;
...@@ -1490,8 +1568,8 @@ xfs_attr3_leaf_rebalance( ...@@ -1490,8 +1568,8 @@ xfs_attr3_leaf_rebalance(
ichdr1.count, count); ichdr1.count, count);
} }
xfs_attr3_leaf_hdr_to_disk(leaf1, &ichdr1); xfs_attr3_leaf_hdr_to_disk(state->args->geo, leaf1, &ichdr1);
xfs_attr3_leaf_hdr_to_disk(leaf2, &ichdr2); xfs_attr3_leaf_hdr_to_disk(state->args->geo, leaf2, &ichdr2);
xfs_trans_log_buf(args->trans, blk1->bp, 0, args->geo->blksize - 1); xfs_trans_log_buf(args->trans, blk1->bp, 0, args->geo->blksize - 1);
xfs_trans_log_buf(args->trans, blk2->bp, 0, args->geo->blksize - 1); xfs_trans_log_buf(args->trans, blk2->bp, 0, args->geo->blksize - 1);
...@@ -1684,7 +1762,7 @@ xfs_attr3_leaf_toosmall( ...@@ -1684,7 +1762,7 @@ xfs_attr3_leaf_toosmall(
*/ */
blk = &state->path.blk[ state->path.active-1 ]; blk = &state->path.blk[ state->path.active-1 ];
leaf = blk->bp->b_addr; leaf = blk->bp->b_addr;
xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf); xfs_attr3_leaf_hdr_from_disk(state->args->geo, &ichdr, leaf);
bytes = xfs_attr3_leaf_hdr_size(leaf) + bytes = xfs_attr3_leaf_hdr_size(leaf) +
ichdr.count * sizeof(xfs_attr_leaf_entry_t) + ichdr.count * sizeof(xfs_attr_leaf_entry_t) +
ichdr.usedbytes; ichdr.usedbytes;
...@@ -1740,7 +1818,7 @@ xfs_attr3_leaf_toosmall( ...@@ -1740,7 +1818,7 @@ xfs_attr3_leaf_toosmall(
if (error) if (error)
return error; return error;
xfs_attr3_leaf_hdr_from_disk(&ichdr2, bp->b_addr); xfs_attr3_leaf_hdr_from_disk(state->args->geo, &ichdr2, bp->b_addr);
bytes = state->args->geo->blksize - bytes = state->args->geo->blksize -
(state->args->geo->blksize >> 2) - (state->args->geo->blksize >> 2) -
...@@ -1805,7 +1883,7 @@ xfs_attr3_leaf_remove( ...@@ -1805,7 +1883,7 @@ xfs_attr3_leaf_remove(
trace_xfs_attr_leaf_remove(args); trace_xfs_attr_leaf_remove(args);
leaf = bp->b_addr; leaf = bp->b_addr;
xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf); xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr, leaf);
ASSERT(ichdr.count > 0 && ichdr.count < args->geo->blksize / 8); ASSERT(ichdr.count > 0 && ichdr.count < args->geo->blksize / 8);
ASSERT(args->index >= 0 && args->index < ichdr.count); ASSERT(args->index >= 0 && args->index < ichdr.count);
...@@ -1918,12 +1996,11 @@ xfs_attr3_leaf_remove( ...@@ -1918,12 +1996,11 @@ xfs_attr3_leaf_remove(
tmp = be16_to_cpu(entry->nameidx); tmp = be16_to_cpu(entry->nameidx);
} }
ichdr.firstused = tmp; ichdr.firstused = tmp;
if (!ichdr.firstused) ASSERT(ichdr.firstused != 0);
ichdr.firstused = tmp - XFS_ATTR_LEAF_NAME_ALIGN;
} else { } else {
ichdr.holes = 1; /* mark as needing compaction */ ichdr.holes = 1; /* mark as needing compaction */
} }
xfs_attr3_leaf_hdr_to_disk(leaf, &ichdr); xfs_attr3_leaf_hdr_to_disk(args->geo, leaf, &ichdr);
xfs_trans_log_buf(args->trans, bp, xfs_trans_log_buf(args->trans, bp,
XFS_DA_LOGRANGE(leaf, &leaf->hdr, XFS_DA_LOGRANGE(leaf, &leaf->hdr,
xfs_attr3_leaf_hdr_size(leaf))); xfs_attr3_leaf_hdr_size(leaf)));
...@@ -1957,8 +2034,8 @@ xfs_attr3_leaf_unbalance( ...@@ -1957,8 +2034,8 @@ xfs_attr3_leaf_unbalance(
drop_leaf = drop_blk->bp->b_addr; drop_leaf = drop_blk->bp->b_addr;
save_leaf = save_blk->bp->b_addr; save_leaf = save_blk->bp->b_addr;
xfs_attr3_leaf_hdr_from_disk(&drophdr, drop_leaf); xfs_attr3_leaf_hdr_from_disk(state->args->geo, &drophdr, drop_leaf);
xfs_attr3_leaf_hdr_from_disk(&savehdr, save_leaf); xfs_attr3_leaf_hdr_from_disk(state->args->geo, &savehdr, save_leaf);
entry = xfs_attr3_leaf_entryp(drop_leaf); entry = xfs_attr3_leaf_entryp(drop_leaf);
/* /*
...@@ -2012,7 +2089,7 @@ xfs_attr3_leaf_unbalance( ...@@ -2012,7 +2089,7 @@ xfs_attr3_leaf_unbalance(
tmphdr.firstused = state->args->geo->blksize; tmphdr.firstused = state->args->geo->blksize;
/* write the header to the temp buffer to initialise it */ /* write the header to the temp buffer to initialise it */
xfs_attr3_leaf_hdr_to_disk(tmp_leaf, &tmphdr); xfs_attr3_leaf_hdr_to_disk(state->args->geo, tmp_leaf, &tmphdr);
if (xfs_attr3_leaf_order(save_blk->bp, &savehdr, if (xfs_attr3_leaf_order(save_blk->bp, &savehdr,
drop_blk->bp, &drophdr)) { drop_blk->bp, &drophdr)) {
...@@ -2039,7 +2116,7 @@ xfs_attr3_leaf_unbalance( ...@@ -2039,7 +2116,7 @@ xfs_attr3_leaf_unbalance(
kmem_free(tmp_leaf); kmem_free(tmp_leaf);
} }
xfs_attr3_leaf_hdr_to_disk(save_leaf, &savehdr); xfs_attr3_leaf_hdr_to_disk(state->args->geo, save_leaf, &savehdr);
xfs_trans_log_buf(state->args->trans, save_blk->bp, 0, xfs_trans_log_buf(state->args->trans, save_blk->bp, 0,
state->args->geo->blksize - 1); state->args->geo->blksize - 1);
...@@ -2085,7 +2162,7 @@ xfs_attr3_leaf_lookup_int( ...@@ -2085,7 +2162,7 @@ xfs_attr3_leaf_lookup_int(
trace_xfs_attr_leaf_lookup(args); trace_xfs_attr_leaf_lookup(args);
leaf = bp->b_addr; leaf = bp->b_addr;
xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf); xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr, leaf);
entries = xfs_attr3_leaf_entryp(leaf); entries = xfs_attr3_leaf_entryp(leaf);
ASSERT(ichdr.count < args->geo->blksize / 8); ASSERT(ichdr.count < args->geo->blksize / 8);
...@@ -2190,7 +2267,7 @@ xfs_attr3_leaf_getvalue( ...@@ -2190,7 +2267,7 @@ xfs_attr3_leaf_getvalue(
int valuelen; int valuelen;
leaf = bp->b_addr; leaf = bp->b_addr;
xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf); xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr, leaf);
ASSERT(ichdr.count < args->geo->blksize / 8); ASSERT(ichdr.count < args->geo->blksize / 8);
ASSERT(args->index < ichdr.count); ASSERT(args->index < ichdr.count);
...@@ -2391,8 +2468,9 @@ xfs_attr_leaf_lasthash( ...@@ -2391,8 +2468,9 @@ xfs_attr_leaf_lasthash(
{ {
struct xfs_attr3_icleaf_hdr ichdr; struct xfs_attr3_icleaf_hdr ichdr;
struct xfs_attr_leaf_entry *entries; struct xfs_attr_leaf_entry *entries;
struct xfs_mount *mp = bp->b_target->bt_mount;
xfs_attr3_leaf_hdr_from_disk(&ichdr, bp->b_addr); xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &ichdr, bp->b_addr);
entries = xfs_attr3_leaf_entryp(bp->b_addr); entries = xfs_attr3_leaf_entryp(bp->b_addr);
if (count) if (count)
*count = ichdr.count; *count = ichdr.count;
...@@ -2486,7 +2564,7 @@ xfs_attr3_leaf_clearflag( ...@@ -2486,7 +2564,7 @@ xfs_attr3_leaf_clearflag(
ASSERT(entry->flags & XFS_ATTR_INCOMPLETE); ASSERT(entry->flags & XFS_ATTR_INCOMPLETE);
#ifdef DEBUG #ifdef DEBUG
xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf); xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr, leaf);
ASSERT(args->index < ichdr.count); ASSERT(args->index < ichdr.count);
ASSERT(args->index >= 0); ASSERT(args->index >= 0);
...@@ -2550,7 +2628,7 @@ xfs_attr3_leaf_setflag( ...@@ -2550,7 +2628,7 @@ xfs_attr3_leaf_setflag(
leaf = bp->b_addr; leaf = bp->b_addr;
#ifdef DEBUG #ifdef DEBUG
xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf); xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr, leaf);
ASSERT(args->index < ichdr.count); ASSERT(args->index < ichdr.count);
ASSERT(args->index >= 0); ASSERT(args->index >= 0);
#endif #endif
...@@ -2629,11 +2707,11 @@ xfs_attr3_leaf_flipflags( ...@@ -2629,11 +2707,11 @@ xfs_attr3_leaf_flipflags(
entry2 = &xfs_attr3_leaf_entryp(leaf2)[args->index2]; entry2 = &xfs_attr3_leaf_entryp(leaf2)[args->index2];
#ifdef DEBUG #ifdef DEBUG
xfs_attr3_leaf_hdr_from_disk(&ichdr1, leaf1); xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr1, leaf1);
ASSERT(args->index < ichdr1.count); ASSERT(args->index < ichdr1.count);
ASSERT(args->index >= 0); ASSERT(args->index >= 0);
xfs_attr3_leaf_hdr_from_disk(&ichdr2, leaf2); xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr2, leaf2);
ASSERT(args->index2 < ichdr2.count); ASSERT(args->index2 < ichdr2.count);
ASSERT(args->index2 >= 0); ASSERT(args->index2 >= 0);
......
...@@ -100,9 +100,11 @@ int xfs_attr_leaf_newentsize(struct xfs_da_args *args, int *local); ...@@ -100,9 +100,11 @@ int xfs_attr_leaf_newentsize(struct xfs_da_args *args, int *local);
int xfs_attr3_leaf_read(struct xfs_trans *tp, struct xfs_inode *dp, int xfs_attr3_leaf_read(struct xfs_trans *tp, struct xfs_inode *dp,
xfs_dablk_t bno, xfs_daddr_t mappedbno, xfs_dablk_t bno, xfs_daddr_t mappedbno,
struct xfs_buf **bpp); struct xfs_buf **bpp);
void xfs_attr3_leaf_hdr_from_disk(struct xfs_attr3_icleaf_hdr *to, void xfs_attr3_leaf_hdr_from_disk(struct xfs_da_geometry *geo,
struct xfs_attr3_icleaf_hdr *to,
struct xfs_attr_leafblock *from); struct xfs_attr_leafblock *from);
void xfs_attr3_leaf_hdr_to_disk(struct xfs_attr_leafblock *to, void xfs_attr3_leaf_hdr_to_disk(struct xfs_da_geometry *geo,
struct xfs_attr_leafblock *to,
struct xfs_attr3_icleaf_hdr *from); struct xfs_attr3_icleaf_hdr *from);
#endif /* __XFS_ATTR_LEAF_H__ */ #endif /* __XFS_ATTR_LEAF_H__ */
...@@ -725,7 +725,13 @@ struct xfs_attr3_icleaf_hdr { ...@@ -725,7 +725,13 @@ struct xfs_attr3_icleaf_hdr {
__uint16_t magic; __uint16_t magic;
__uint16_t count; __uint16_t count;
__uint16_t usedbytes; __uint16_t usedbytes;
__uint16_t firstused; /*
* firstused is 32-bit here instead of 16-bit like the on-disk variant
* to support maximum fsb size of 64k without overflow issues throughout
* the attr code. Instead, the overflow condition is handled on
* conversion to/from disk.
*/
__uint32_t firstused;
__u8 holes; __u8 holes;
struct { struct {
__uint16_t base; __uint16_t base;
...@@ -733,6 +739,12 @@ struct xfs_attr3_icleaf_hdr { ...@@ -733,6 +739,12 @@ struct xfs_attr3_icleaf_hdr {
} freemap[XFS_ATTR_LEAF_MAPSIZE]; } freemap[XFS_ATTR_LEAF_MAPSIZE];
}; };
/*
* 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. * Flags used in the leaf_entry[i].flags field.
* NOTE: the INCOMPLETE bit must not collide with the flags bits specified * NOTE: the INCOMPLETE bit must not collide with the flags bits specified
......
...@@ -132,9 +132,10 @@ xfs_attr3_leaf_inactive( ...@@ -132,9 +132,10 @@ xfs_attr3_leaf_inactive(
int size; int size;
int tmp; int tmp;
int i; int i;
struct xfs_mount *mp = bp->b_target->bt_mount;
leaf = bp->b_addr; leaf = bp->b_addr;
xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf); xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &ichdr, leaf);
/* /*
* Count the number of "remote" value extents. * Count the number of "remote" value extents.
......
...@@ -225,6 +225,7 @@ xfs_attr_node_list(xfs_attr_list_context_t *context) ...@@ -225,6 +225,7 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
int error, i; int error, i;
struct xfs_buf *bp; struct xfs_buf *bp;
struct xfs_inode *dp = context->dp; struct xfs_inode *dp = context->dp;
struct xfs_mount *mp = dp->i_mount;
trace_xfs_attr_node_list(context); trace_xfs_attr_node_list(context);
...@@ -256,7 +257,8 @@ xfs_attr_node_list(xfs_attr_list_context_t *context) ...@@ -256,7 +257,8 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
case XFS_ATTR_LEAF_MAGIC: case XFS_ATTR_LEAF_MAGIC:
case XFS_ATTR3_LEAF_MAGIC: case XFS_ATTR3_LEAF_MAGIC:
leaf = bp->b_addr; leaf = bp->b_addr;
xfs_attr3_leaf_hdr_from_disk(&leafhdr, leaf); xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo,
&leafhdr, leaf);
entries = xfs_attr3_leaf_entryp(leaf); entries = xfs_attr3_leaf_entryp(leaf);
if (cursor->hashval > be32_to_cpu( if (cursor->hashval > be32_to_cpu(
entries[leafhdr.count - 1].hashval)) { entries[leafhdr.count - 1].hashval)) {
...@@ -340,7 +342,7 @@ xfs_attr_node_list(xfs_attr_list_context_t *context) ...@@ -340,7 +342,7 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
xfs_trans_brelse(NULL, bp); xfs_trans_brelse(NULL, bp);
return error; return error;
} }
xfs_attr3_leaf_hdr_from_disk(&leafhdr, leaf); xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &leafhdr, leaf);
if (context->seen_enough || leafhdr.forw == 0) if (context->seen_enough || leafhdr.forw == 0)
break; break;
cursor->blkno = leafhdr.forw; cursor->blkno = leafhdr.forw;
...@@ -368,11 +370,12 @@ xfs_attr3_leaf_list_int( ...@@ -368,11 +370,12 @@ xfs_attr3_leaf_list_int(
struct xfs_attr_leaf_entry *entry; struct xfs_attr_leaf_entry *entry;
int retval; int retval;
int i; int i;
struct xfs_mount *mp = context->dp->i_mount;
trace_xfs_attr_list_leaf(context); trace_xfs_attr_list_leaf(context);
leaf = bp->b_addr; leaf = bp->b_addr;
xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf); xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &ichdr, leaf);
entries = xfs_attr3_leaf_entryp(leaf); entries = xfs_attr3_leaf_entryp(leaf);
cursor = context->cursor; cursor = context->cursor;
......
...@@ -1383,7 +1383,7 @@ xfs_zero_file_space( ...@@ -1383,7 +1383,7 @@ xfs_zero_file_space(
* If we are shifting right, we will start with last extent inside file space * If we are shifting right, we will start with last extent inside file space
* and continue until we reach the block corresponding to offset. * and continue until we reach the block corresponding to offset.
*/ */
int static int
xfs_shift_file_space( xfs_shift_file_space(
struct xfs_inode *ip, struct xfs_inode *ip,
xfs_off_t offset, xfs_off_t offset,
......
...@@ -559,7 +559,7 @@ xfs_file_aio_write_checks( ...@@ -559,7 +559,7 @@ xfs_file_aio_write_checks(
if (error) if (error)
return error; return error;
error = xfs_break_layouts(inode, iolock); error = xfs_break_layouts(inode, iolock, true);
if (error) if (error)
return error; return error;
...@@ -848,7 +848,7 @@ xfs_file_fallocate( ...@@ -848,7 +848,7 @@ xfs_file_fallocate(
return -EOPNOTSUPP; return -EOPNOTSUPP;
xfs_ilock(ip, iolock); xfs_ilock(ip, iolock);
error = xfs_break_layouts(inode, &iolock); error = xfs_break_layouts(inode, &iolock, false);
if (error) if (error)
goto out_unlock; goto out_unlock;
......
...@@ -639,7 +639,7 @@ xfs_ioc_space( ...@@ -639,7 +639,7 @@ xfs_ioc_space(
return error; return error;
xfs_ilock(ip, iolock); xfs_ilock(ip, iolock);
error = xfs_break_layouts(inode, &iolock); error = xfs_break_layouts(inode, &iolock, false);
if (error) if (error)
goto out_unlock; goto out_unlock;
......
...@@ -953,7 +953,7 @@ xfs_vn_setattr( ...@@ -953,7 +953,7 @@ xfs_vn_setattr(
uint iolock = XFS_IOLOCK_EXCL; uint iolock = XFS_IOLOCK_EXCL;
xfs_ilock(ip, iolock); xfs_ilock(ip, iolock);
error = xfs_break_layouts(dentry->d_inode, &iolock); error = xfs_break_layouts(dentry->d_inode, &iolock, true);
if (!error) { if (!error) {
xfs_ilock(ip, XFS_MMAPLOCK_EXCL); xfs_ilock(ip, XFS_MMAPLOCK_EXCL);
iolock |= XFS_MMAPLOCK_EXCL; iolock |= XFS_MMAPLOCK_EXCL;
......
...@@ -31,7 +31,8 @@ ...@@ -31,7 +31,8 @@
int int
xfs_break_layouts( xfs_break_layouts(
struct inode *inode, struct inode *inode,
uint *iolock) uint *iolock,
bool with_imutex)
{ {
struct xfs_inode *ip = XFS_I(inode); struct xfs_inode *ip = XFS_I(inode);
int error; int error;
...@@ -40,8 +41,12 @@ xfs_break_layouts( ...@@ -40,8 +41,12 @@ xfs_break_layouts(
while ((error = break_layout(inode, false) == -EWOULDBLOCK)) { while ((error = break_layout(inode, false) == -EWOULDBLOCK)) {
xfs_iunlock(ip, *iolock); xfs_iunlock(ip, *iolock);
if (with_imutex && (*iolock & XFS_IOLOCK_EXCL))
mutex_unlock(&inode->i_mutex);
error = break_layout(inode, true); error = break_layout(inode, true);
*iolock = XFS_IOLOCK_EXCL; *iolock = XFS_IOLOCK_EXCL;
if (with_imutex)
mutex_lock(&inode->i_mutex);
xfs_ilock(ip, *iolock); xfs_ilock(ip, *iolock);
} }
......
...@@ -8,9 +8,10 @@ int xfs_fs_map_blocks(struct inode *inode, loff_t offset, u64 length, ...@@ -8,9 +8,10 @@ int xfs_fs_map_blocks(struct inode *inode, loff_t offset, u64 length,
int xfs_fs_commit_blocks(struct inode *inode, struct iomap *maps, int nr_maps, int xfs_fs_commit_blocks(struct inode *inode, struct iomap *maps, int nr_maps,
struct iattr *iattr); struct iattr *iattr);
int xfs_break_layouts(struct inode *inode, uint *iolock); int xfs_break_layouts(struct inode *inode, uint *iolock, bool with_imutex);
#else #else
static inline int xfs_break_layouts(struct inode *inode, uint *iolock) static inline int
xfs_break_layouts(struct inode *inode, uint *iolock, bool with_imutex)
{ {
return 0; return 0;
} }
......
...@@ -1227,6 +1227,12 @@ xfs_fs_remount( ...@@ -1227,6 +1227,12 @@ xfs_fs_remount(
/* ro -> rw */ /* ro -> rw */
if ((mp->m_flags & XFS_MOUNT_RDONLY) && !(*flags & MS_RDONLY)) { if ((mp->m_flags & XFS_MOUNT_RDONLY) && !(*flags & MS_RDONLY)) {
if (mp->m_flags & XFS_MOUNT_NORECOVERY) {
xfs_warn(mp,
"ro->rw transition prohibited on norecovery mount");
return -EINVAL;
}
mp->m_flags &= ~XFS_MOUNT_RDONLY; mp->m_flags &= ~XFS_MOUNT_RDONLY;
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment