Commit d9627cf4 authored by Nathan Scott's avatar Nathan Scott

[XFS] Fix xfs_da_node_split handling of dir/attr buffers for filesystems built

with a directory block size larger than the filesystem (and hence attr)
blocksize.  This does not affect filesystems built with default mkfs.xfs
parameters, and only hits when a large number of attributes are set on
an inode.

SGI Modid: 2.5.x-xfs:slinx:130577a
parent 7a1ca765
...@@ -1170,6 +1170,7 @@ xfs_attr_node_addname(xfs_da_args_t *args) ...@@ -1170,6 +1170,7 @@ xfs_attr_node_addname(xfs_da_args_t *args)
state->args = args; state->args = args;
state->mp = mp; state->mp = mp;
state->blocksize = state->mp->m_sb.sb_blocksize; state->blocksize = state->mp->m_sb.sb_blocksize;
state->node_ents = state->mp->m_attr_node_ents;
/* /*
* Search to see if name already exists, and get back a pointer * Search to see if name already exists, and get back a pointer
...@@ -1337,6 +1338,7 @@ xfs_attr_node_addname(xfs_da_args_t *args) ...@@ -1337,6 +1338,7 @@ xfs_attr_node_addname(xfs_da_args_t *args)
state->args = args; state->args = args;
state->mp = mp; state->mp = mp;
state->blocksize = state->mp->m_sb.sb_blocksize; state->blocksize = state->mp->m_sb.sb_blocksize;
state->node_ents = state->mp->m_attr_node_ents;
state->inleaf = 0; state->inleaf = 0;
error = xfs_da_node_lookup_int(state, &retval); error = xfs_da_node_lookup_int(state, &retval);
if (error) if (error)
...@@ -1428,6 +1430,7 @@ xfs_attr_node_removename(xfs_da_args_t *args) ...@@ -1428,6 +1430,7 @@ xfs_attr_node_removename(xfs_da_args_t *args)
state->args = args; state->args = args;
state->mp = dp->i_mount; state->mp = dp->i_mount;
state->blocksize = state->mp->m_sb.sb_blocksize; state->blocksize = state->mp->m_sb.sb_blocksize;
state->node_ents = state->mp->m_attr_node_ents;
/* /*
* Search to see if name exists, and get back a pointer to it. * Search to see if name exists, and get back a pointer to it.
...@@ -1695,6 +1698,7 @@ xfs_attr_node_get(xfs_da_args_t *args) ...@@ -1695,6 +1698,7 @@ xfs_attr_node_get(xfs_da_args_t *args)
state->args = args; state->args = args;
state->mp = args->dp->i_mount; state->mp = args->dp->i_mount;
state->blocksize = state->mp->m_sb.sb_blocksize; state->blocksize = state->mp->m_sb.sb_blocksize;
state->node_ents = state->mp->m_attr_node_ents;
/* /*
* Search to see if name exists, and get back a pointer to it. * Search to see if name exists, and get back a pointer to it.
......
...@@ -381,12 +381,16 @@ xfs_da_root_split(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, ...@@ -381,12 +381,16 @@ xfs_da_root_split(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
INT_SET(node->btree[1].hashval, ARCH_CONVERT, blk2->hashval); INT_SET(node->btree[1].hashval, ARCH_CONVERT, blk2->hashval);
INT_SET(node->btree[1].before, ARCH_CONVERT, blk2->blkno); INT_SET(node->btree[1].before, ARCH_CONVERT, blk2->blkno);
INT_SET(node->hdr.count, ARCH_CONVERT, 2); INT_SET(node->hdr.count, ARCH_CONVERT, 2);
if (XFS_DIR_IS_V2(mp)) {
#ifdef DEBUG
if (INT_GET(oldroot->hdr.info.magic, ARCH_CONVERT) == XFS_DIR2_LEAFN_MAGIC) {
ASSERT(blk1->blkno >= mp->m_dirleafblk && ASSERT(blk1->blkno >= mp->m_dirleafblk &&
blk1->blkno < mp->m_dirfreeblk); blk1->blkno < mp->m_dirfreeblk);
ASSERT(blk2->blkno >= mp->m_dirleafblk && ASSERT(blk2->blkno >= mp->m_dirleafblk &&
blk2->blkno < mp->m_dirfreeblk); blk2->blkno < mp->m_dirfreeblk);
} }
#endif
/* Header is already logged by xfs_da_node_create */ /* Header is already logged by xfs_da_node_create */
xfs_da_log_buf(tp, bp, xfs_da_log_buf(tp, bp,
XFS_DA_LOGRANGE(node, node->btree, XFS_DA_LOGRANGE(node, node->btree,
...@@ -421,7 +425,7 @@ xfs_da_node_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk, ...@@ -421,7 +425,7 @@ xfs_da_node_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk,
/* /*
* Do we have to split the node? * Do we have to split the node?
*/ */
if ((INT_GET(node->hdr.count, ARCH_CONVERT) + newcount) > XFS_DA_NODE_ENTRIES(state->mp)) { if ((INT_GET(node->hdr.count, ARCH_CONVERT) + newcount) > state->node_ents) {
/* /*
* Allocate a new node, add to the doubly linked chain of * Allocate a new node, add to the doubly linked chain of
* nodes, then move some of our excess entries into it. * nodes, then move some of our excess entries into it.
...@@ -825,7 +829,7 @@ xfs_da_node_toosmall(xfs_da_state_t *state, int *action) ...@@ -825,7 +829,7 @@ xfs_da_node_toosmall(xfs_da_state_t *state, int *action)
ASSERT(INT_GET(info->magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC); ASSERT(INT_GET(info->magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC);
node = (xfs_da_intnode_t *)info; node = (xfs_da_intnode_t *)info;
count = INT_GET(node->hdr.count, ARCH_CONVERT); count = INT_GET(node->hdr.count, ARCH_CONVERT);
if (count > (XFS_DA_NODE_ENTRIES(state->mp) >> 1)) { if (count > (state->node_ents >> 1)) {
*action = 0; /* blk over 50%, dont try to join */ *action = 0; /* blk over 50%, dont try to join */
return(0); /* blk over 50%, dont try to join */ return(0); /* blk over 50%, dont try to join */
} }
...@@ -879,8 +883,8 @@ xfs_da_node_toosmall(xfs_da_state_t *state, int *action) ...@@ -879,8 +883,8 @@ xfs_da_node_toosmall(xfs_da_state_t *state, int *action)
ASSERT(bp != NULL); ASSERT(bp != NULL);
node = (xfs_da_intnode_t *)info; node = (xfs_da_intnode_t *)info;
count = XFS_DA_NODE_ENTRIES(state->mp); count = state->node_ents;
count -= XFS_DA_NODE_ENTRIES(state->mp) >> 2; count -= state->node_ents >> 2;
count -= INT_GET(node->hdr.count, ARCH_CONVERT); count -= INT_GET(node->hdr.count, ARCH_CONVERT);
node = bp->data; node = bp->data;
ASSERT(INT_GET(node->hdr.info.magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC); ASSERT(INT_GET(node->hdr.info.magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC);
......
...@@ -90,15 +90,6 @@ typedef struct xfs_da_intnode { ...@@ -90,15 +90,6 @@ typedef struct xfs_da_intnode {
typedef struct xfs_da_node_hdr xfs_da_node_hdr_t; typedef struct xfs_da_node_hdr xfs_da_node_hdr_t;
typedef struct xfs_da_node_entry xfs_da_node_entry_t; typedef struct xfs_da_node_entry xfs_da_node_entry_t;
#define XFS_DA_NODE_ENTSIZE_BYNAME /* space a name uses */ \
(sizeof(xfs_da_node_entry_t))
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_DA_NODE_ENTRIES)
int xfs_da_node_entries(struct xfs_mount *mp);
#define XFS_DA_NODE_ENTRIES(mp) xfs_da_node_entries(mp)
#else
#define XFS_DA_NODE_ENTRIES(mp) ((mp)->m_da_node_ents)
#endif
#define XFS_DA_MAXHASH ((xfs_dahash_t)-1) /* largest valid hash value */ #define XFS_DA_MAXHASH ((xfs_dahash_t)-1) /* largest valid hash value */
/* /*
...@@ -243,7 +234,7 @@ extern xfs_dabuf_t *xfs_dabuf_global_list; ...@@ -243,7 +234,7 @@ extern xfs_dabuf_t *xfs_dabuf_global_list;
typedef struct xfs_da_state_blk { typedef struct xfs_da_state_blk {
xfs_dabuf_t *bp; /* buffer containing block */ xfs_dabuf_t *bp; /* buffer containing block */
xfs_dablk_t blkno; /* filesystem blkno of buffer */ xfs_dablk_t blkno; /* filesystem blkno of buffer */
xfs_daddr_t disk_blkno; /* on-disk blkno (in BBs) of buffer */ xfs_daddr_t disk_blkno; /* on-disk blkno (in BBs) of buffer */
int index; /* relevant index into block */ int index; /* relevant index into block */
xfs_dahash_t hashval; /* last hash value in block */ xfs_dahash_t hashval; /* last hash value in block */
int magic; /* blk's magic number, ie: blk type */ int magic; /* blk's magic number, ie: blk type */
...@@ -257,12 +248,13 @@ typedef struct xfs_da_state_path { ...@@ -257,12 +248,13 @@ typedef struct xfs_da_state_path {
typedef struct xfs_da_state { typedef struct xfs_da_state {
xfs_da_args_t *args; /* filename arguments */ xfs_da_args_t *args; /* filename arguments */
struct xfs_mount *mp; /* filesystem mount point */ struct xfs_mount *mp; /* filesystem mount point */
int blocksize; /* logical block size */ unsigned int blocksize; /* logical block size */
int inleaf; /* insert into 1->lf, 0->splf */ unsigned int node_ents; /* how many entries in danode */
xfs_da_state_path_t path; /* search/split paths */ xfs_da_state_path_t path; /* search/split paths */
xfs_da_state_path_t altpath; /* alternate path for join */ xfs_da_state_path_t altpath; /* alternate path for join */
int extravalid; /* T/F: extrablk is in use */ unsigned int inleaf : 1; /* insert into 1->lf, 0->splf */
int extraafter; /* T/F: extrablk is after new */ unsigned int extravalid : 1; /* T/F: extrablk is in use */
unsigned int extraafter : 1; /* T/F: extrablk is after new */
xfs_da_state_blk_t extrablk; /* for double-splits on leafs */ xfs_da_state_blk_t extrablk; /* for double-splits on leafs */
/* for dirv2 extrablk is data */ /* for dirv2 extrablk is data */
} xfs_da_state_t; } xfs_da_state_t;
......
...@@ -176,7 +176,7 @@ xfs_dir_mount(xfs_mount_t *mp) ...@@ -176,7 +176,7 @@ xfs_dir_mount(xfs_mount_t *mp)
count = shortcount > leafcount ? shortcount : leafcount; count = shortcount > leafcount ? shortcount : leafcount;
mp->m_dircook_elog = xfs_da_log2_roundup(count + 1); mp->m_dircook_elog = xfs_da_log2_roundup(count + 1);
ASSERT(mp->m_dircook_elog <= mp->m_sb.sb_blocklog); ASSERT(mp->m_dircook_elog <= mp->m_sb.sb_blocklog);
mp->m_da_node_ents = mp->m_dir_node_ents = mp->m_attr_node_ents =
(XFS_LBSIZE(mp) - (uint)sizeof(xfs_da_node_hdr_t)) / (XFS_LBSIZE(mp) - (uint)sizeof(xfs_da_node_hdr_t)) /
(uint)sizeof(xfs_da_node_entry_t); (uint)sizeof(xfs_da_node_entry_t);
mp->m_dir_magicpct = (XFS_LBSIZE(mp) * 37) / 100; mp->m_dir_magicpct = (XFS_LBSIZE(mp) * 37) / 100;
...@@ -734,6 +734,7 @@ xfs_dir_node_addname(xfs_da_args_t *args) ...@@ -734,6 +734,7 @@ xfs_dir_node_addname(xfs_da_args_t *args)
state->args = args; state->args = args;
state->mp = args->dp->i_mount; state->mp = args->dp->i_mount;
state->blocksize = state->mp->m_sb.sb_blocksize; state->blocksize = state->mp->m_sb.sb_blocksize;
state->node_ents = state->mp->m_dir_node_ents;
/* /*
* Search to see if name already exists, and get back a pointer * Search to see if name already exists, and get back a pointer
...@@ -787,6 +788,7 @@ xfs_dir_node_removename(xfs_da_args_t *args) ...@@ -787,6 +788,7 @@ xfs_dir_node_removename(xfs_da_args_t *args)
state->args = args; state->args = args;
state->mp = args->dp->i_mount; state->mp = args->dp->i_mount;
state->blocksize = state->mp->m_sb.sb_blocksize; state->blocksize = state->mp->m_sb.sb_blocksize;
state->node_ents = state->mp->m_dir_node_ents;
/* /*
* Search to see if name exists, and get back a pointer to it. * Search to see if name exists, and get back a pointer to it.
...@@ -835,6 +837,7 @@ xfs_dir_node_lookup(xfs_da_args_t *args) ...@@ -835,6 +837,7 @@ xfs_dir_node_lookup(xfs_da_args_t *args)
state->args = args; state->args = args;
state->mp = args->dp->i_mount; state->mp = args->dp->i_mount;
state->blocksize = state->mp->m_sb.sb_blocksize; state->blocksize = state->mp->m_sb.sb_blocksize;
state->node_ents = state->mp->m_dir_node_ents;
/* /*
* Search to see if name exists, * Search to see if name exists,
...@@ -1019,6 +1022,7 @@ xfs_dir_node_replace(xfs_da_args_t *args) ...@@ -1019,6 +1022,7 @@ xfs_dir_node_replace(xfs_da_args_t *args)
state->args = args; state->args = args;
state->mp = args->dp->i_mount; state->mp = args->dp->i_mount;
state->blocksize = state->mp->m_sb.sb_blocksize; state->blocksize = state->mp->m_sb.sb_blocksize;
state->node_ents = state->mp->m_dir_node_ents;
inum = args->inumber; inum = args->inumber;
/* /*
......
...@@ -107,7 +107,10 @@ xfs_dir2_mount( ...@@ -107,7 +107,10 @@ xfs_dir2_mount(
mp->m_dirdatablk = XFS_DIR2_DB_TO_DA(mp, XFS_DIR2_DATA_FIRSTDB(mp)); mp->m_dirdatablk = XFS_DIR2_DB_TO_DA(mp, XFS_DIR2_DATA_FIRSTDB(mp));
mp->m_dirleafblk = XFS_DIR2_DB_TO_DA(mp, XFS_DIR2_LEAF_FIRSTDB(mp)); mp->m_dirleafblk = XFS_DIR2_DB_TO_DA(mp, XFS_DIR2_LEAF_FIRSTDB(mp));
mp->m_dirfreeblk = XFS_DIR2_DB_TO_DA(mp, XFS_DIR2_FREE_FIRSTDB(mp)); mp->m_dirfreeblk = XFS_DIR2_DB_TO_DA(mp, XFS_DIR2_FREE_FIRSTDB(mp));
mp->m_da_node_ents = mp->m_attr_node_ents =
(mp->m_sb.sb_blocksize - (uint)sizeof(xfs_da_node_hdr_t)) /
(uint)sizeof(xfs_da_node_entry_t);
mp->m_dir_node_ents =
(mp->m_dirblksize - (uint)sizeof(xfs_da_node_hdr_t)) / (mp->m_dirblksize - (uint)sizeof(xfs_da_node_hdr_t)) /
(uint)sizeof(xfs_da_node_entry_t); (uint)sizeof(xfs_da_node_entry_t);
mp->m_dir_magicpct = (mp->m_dirblksize * 37) / 100; mp->m_dir_magicpct = (mp->m_dirblksize * 37) / 100;
......
...@@ -1274,6 +1274,7 @@ xfs_dir2_node_addname( ...@@ -1274,6 +1274,7 @@ xfs_dir2_node_addname(
state->args = args; state->args = args;
state->mp = args->dp->i_mount; state->mp = args->dp->i_mount;
state->blocksize = state->mp->m_dirblksize; state->blocksize = state->mp->m_dirblksize;
state->node_ents = state->mp->m_dir_node_ents;
/* /*
* Look up the name. We're not supposed to find it, but * Look up the name. We're not supposed to find it, but
* this gives us the insertion point. * this gives us the insertion point.
...@@ -1747,6 +1748,7 @@ xfs_dir2_node_lookup( ...@@ -1747,6 +1748,7 @@ xfs_dir2_node_lookup(
state->args = args; state->args = args;
state->mp = args->dp->i_mount; state->mp = args->dp->i_mount;
state->blocksize = state->mp->m_dirblksize; state->blocksize = state->mp->m_dirblksize;
state->node_ents = state->mp->m_dir_node_ents;
/* /*
* Fill in the path to the entry in the cursor. * Fill in the path to the entry in the cursor.
*/ */
...@@ -1791,6 +1793,7 @@ xfs_dir2_node_removename( ...@@ -1791,6 +1793,7 @@ xfs_dir2_node_removename(
state->args = args; state->args = args;
state->mp = args->dp->i_mount; state->mp = args->dp->i_mount;
state->blocksize = state->mp->m_dirblksize; state->blocksize = state->mp->m_dirblksize;
state->node_ents = state->mp->m_dir_node_ents;
/* /*
* Look up the entry we're deleting, set up the cursor. * Look up the entry we're deleting, set up the cursor.
*/ */
...@@ -1861,6 +1864,7 @@ xfs_dir2_node_replace( ...@@ -1861,6 +1864,7 @@ xfs_dir2_node_replace(
state->args = args; state->args = args;
state->mp = args->dp->i_mount; state->mp = args->dp->i_mount;
state->blocksize = state->mp->m_dirblksize; state->blocksize = state->mp->m_dirblksize;
state->node_ents = state->mp->m_dir_node_ents;
inum = args->inumber; inum = args->inumber;
/* /*
* Lookup the entry to change in the btree. * Lookup the entry to change in the btree.
......
...@@ -854,14 +854,6 @@ xfs_da_make_cookie(xfs_mount_t *mp, xfs_dablk_t bno, int entry, ...@@ -854,14 +854,6 @@ xfs_da_make_cookie(xfs_mount_t *mp, xfs_dablk_t bno, int entry,
} }
#endif #endif
#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_DA_NODE_ENTRIES)
int
xfs_da_node_entries(xfs_mount_t *mp)
{
return XFS_DA_NODE_ENTRIES(mp);
}
#endif
#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_DADDR_TO_AGBNO) #if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_DADDR_TO_AGBNO)
xfs_agblock_t xfs_agblock_t
xfs_daddr_to_agbno(xfs_mount_t *mp, xfs_daddr_t d) xfs_daddr_to_agbno(xfs_mount_t *mp, xfs_daddr_t d)
......
...@@ -209,7 +209,8 @@ typedef struct xfs_mount { ...@@ -209,7 +209,8 @@ typedef struct xfs_mount {
uint m_dmevmask; /* DMI events for this FS */ uint m_dmevmask; /* DMI events for this FS */
uint m_flags; /* global mount flags */ uint m_flags; /* global mount flags */
uint m_attroffset; /* inode attribute offset */ uint m_attroffset; /* inode attribute offset */
int m_da_node_ents; /* how many entries in danode */ uint m_dir_node_ents; /* #entries in a dir danode */
uint m_attr_node_ents; /* #entries in attr danode */
int m_ialloc_inos; /* inodes in inode allocation */ int m_ialloc_inos; /* inodes in inode allocation */
int m_ialloc_blks; /* blocks in inode allocation */ int m_ialloc_blks; /* blocks in inode allocation */
int m_litino; /* size of inode union area */ int m_litino; /* size of inode union area */
......
...@@ -3725,8 +3725,8 @@ xfsidbg_xdastate(xfs_da_state_t *s) ...@@ -3725,8 +3725,8 @@ xfsidbg_xdastate(xfs_da_state_t *s)
{ {
xfs_da_state_blk_t *eblk; xfs_da_state_blk_t *eblk;
kdb_printf("args 0x%p mp 0x%p blocksize %d inleaf %d\n", kdb_printf("args 0x%p mp 0x%p blocksize %u node_ents %u inleaf %u\n",
s->args, s->mp, s->blocksize, s->inleaf); s->args, s->mp, s->blocksize, s->node_ents, s->inleaf);
if (s->args) if (s->args)
xfsidbg_xdaargs(s->args); xfsidbg_xdaargs(s->args);
...@@ -4637,9 +4637,10 @@ xfsidbg_xmount(xfs_mount_t *mp) ...@@ -4637,9 +4637,10 @@ xfsidbg_xmount(xfs_mount_t *mp)
printflags(mp->m_flags, xmount_flags,"flags"); printflags(mp->m_flags, xmount_flags,"flags");
kdb_printf("ialloc_inos %d ialloc_blks %d litino %d\n", kdb_printf("ialloc_inos %d ialloc_blks %d litino %d\n",
mp->m_ialloc_inos, mp->m_ialloc_blks, mp->m_litino); mp->m_ialloc_inos, mp->m_ialloc_blks, mp->m_litino);
kdb_printf("attroffset %d da_node_ents %d maxicount %Ld inoalign_mask %d\n", kdb_printf("dir_node_ents %u attr_node_ents %u\n",
mp->m_attroffset, mp->m_da_node_ents, mp->m_maxicount, mp->m_dir_node_ents, mp->m_attr_node_ents);
mp->m_inoalign_mask); kdb_printf("attroffset %d maxicount %Ld inoalign_mask %d\n",
mp->m_attroffset, mp->m_maxicount, mp->m_inoalign_mask);
kdb_printf("resblks %Ld resblks_avail %Ld\n", mp->m_resblks, kdb_printf("resblks %Ld resblks_avail %Ld\n", mp->m_resblks,
mp->m_resblks_avail); mp->m_resblks_avail);
#if XFS_BIG_FILESYSTEMS #if XFS_BIG_FILESYSTEMS
......
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