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)
state->args = args;
state->mp = mp;
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
......@@ -1337,6 +1338,7 @@ xfs_attr_node_addname(xfs_da_args_t *args)
state->args = args;
state->mp = mp;
state->blocksize = state->mp->m_sb.sb_blocksize;
state->node_ents = state->mp->m_attr_node_ents;
state->inleaf = 0;
error = xfs_da_node_lookup_int(state, &retval);
if (error)
......@@ -1428,6 +1430,7 @@ xfs_attr_node_removename(xfs_da_args_t *args)
state->args = args;
state->mp = dp->i_mount;
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.
......@@ -1695,6 +1698,7 @@ xfs_attr_node_get(xfs_da_args_t *args)
state->args = args;
state->mp = args->dp->i_mount;
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.
......
......@@ -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].before, ARCH_CONVERT, blk2->blkno);
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 &&
blk1->blkno < mp->m_dirfreeblk);
ASSERT(blk2->blkno >= mp->m_dirleafblk &&
blk2->blkno < mp->m_dirfreeblk);
}
#endif
/* Header is already logged by xfs_da_node_create */
xfs_da_log_buf(tp, bp,
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,
/*
* 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
* 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)
ASSERT(INT_GET(info->magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC);
node = (xfs_da_intnode_t *)info;
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 */
return(0); /* blk over 50%, dont try to join */
}
......@@ -879,8 +883,8 @@ xfs_da_node_toosmall(xfs_da_state_t *state, int *action)
ASSERT(bp != NULL);
node = (xfs_da_intnode_t *)info;
count = XFS_DA_NODE_ENTRIES(state->mp);
count -= XFS_DA_NODE_ENTRIES(state->mp) >> 2;
count = state->node_ents;
count -= state->node_ents >> 2;
count -= INT_GET(node->hdr.count, ARCH_CONVERT);
node = bp->data;
ASSERT(INT_GET(node->hdr.info.magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC);
......
......@@ -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_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 */
/*
......@@ -243,7 +234,7 @@ extern xfs_dabuf_t *xfs_dabuf_global_list;
typedef struct xfs_da_state_blk {
xfs_dabuf_t *bp; /* buffer containing block */
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 */
xfs_dahash_t hashval; /* last hash value in block */
int magic; /* blk's magic number, ie: blk type */
......@@ -257,12 +248,13 @@ typedef struct xfs_da_state_path {
typedef struct xfs_da_state {
xfs_da_args_t *args; /* filename arguments */
struct xfs_mount *mp; /* filesystem mount point */
int blocksize; /* logical block size */
int inleaf; /* insert into 1->lf, 0->splf */
unsigned int blocksize; /* logical block size */
unsigned int node_ents; /* how many entries in danode */
xfs_da_state_path_t path; /* search/split paths */
xfs_da_state_path_t altpath; /* alternate path for join */
int extravalid; /* T/F: extrablk is in use */
int extraafter; /* T/F: extrablk is after new */
unsigned int inleaf : 1; /* insert into 1->lf, 0->splf */
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 */
/* for dirv2 extrablk is data */
} xfs_da_state_t;
......
......@@ -176,7 +176,7 @@ xfs_dir_mount(xfs_mount_t *mp)
count = shortcount > leafcount ? shortcount : leafcount;
mp->m_dircook_elog = xfs_da_log2_roundup(count + 1);
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)) /
(uint)sizeof(xfs_da_node_entry_t);
mp->m_dir_magicpct = (XFS_LBSIZE(mp) * 37) / 100;
......@@ -734,6 +734,7 @@ xfs_dir_node_addname(xfs_da_args_t *args)
state->args = args;
state->mp = args->dp->i_mount;
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
......@@ -787,6 +788,7 @@ xfs_dir_node_removename(xfs_da_args_t *args)
state->args = args;
state->mp = args->dp->i_mount;
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.
......@@ -835,6 +837,7 @@ xfs_dir_node_lookup(xfs_da_args_t *args)
state->args = args;
state->mp = args->dp->i_mount;
state->blocksize = state->mp->m_sb.sb_blocksize;
state->node_ents = state->mp->m_dir_node_ents;
/*
* Search to see if name exists,
......@@ -1019,6 +1022,7 @@ xfs_dir_node_replace(xfs_da_args_t *args)
state->args = args;
state->mp = args->dp->i_mount;
state->blocksize = state->mp->m_sb.sb_blocksize;
state->node_ents = state->mp->m_dir_node_ents;
inum = args->inumber;
/*
......
......@@ -107,7 +107,10 @@ xfs_dir2_mount(
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_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)) /
(uint)sizeof(xfs_da_node_entry_t);
mp->m_dir_magicpct = (mp->m_dirblksize * 37) / 100;
......
......@@ -1274,6 +1274,7 @@ xfs_dir2_node_addname(
state->args = args;
state->mp = args->dp->i_mount;
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
* this gives us the insertion point.
......@@ -1747,6 +1748,7 @@ xfs_dir2_node_lookup(
state->args = args;
state->mp = args->dp->i_mount;
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.
*/
......@@ -1791,6 +1793,7 @@ xfs_dir2_node_removename(
state->args = args;
state->mp = args->dp->i_mount;
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.
*/
......@@ -1861,6 +1864,7 @@ xfs_dir2_node_replace(
state->args = args;
state->mp = args->dp->i_mount;
state->blocksize = state->mp->m_dirblksize;
state->node_ents = state->mp->m_dir_node_ents;
inum = args->inumber;
/*
* 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,
}
#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)
xfs_agblock_t
xfs_daddr_to_agbno(xfs_mount_t *mp, xfs_daddr_t d)
......
......@@ -209,7 +209,8 @@ typedef struct xfs_mount {
uint m_dmevmask; /* DMI events for this FS */
uint m_flags; /* global mount flags */
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_blks; /* blocks in inode allocation */
int m_litino; /* size of inode union area */
......
......@@ -3725,8 +3725,8 @@ xfsidbg_xdastate(xfs_da_state_t *s)
{
xfs_da_state_blk_t *eblk;
kdb_printf("args 0x%p mp 0x%p blocksize %d inleaf %d\n",
s->args, s->mp, s->blocksize, s->inleaf);
kdb_printf("args 0x%p mp 0x%p blocksize %u node_ents %u inleaf %u\n",
s->args, s->mp, s->blocksize, s->node_ents, s->inleaf);
if (s->args)
xfsidbg_xdaargs(s->args);
......@@ -4637,9 +4637,10 @@ xfsidbg_xmount(xfs_mount_t *mp)
printflags(mp->m_flags, xmount_flags,"flags");
kdb_printf("ialloc_inos %d ialloc_blks %d litino %d\n",
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",
mp->m_attroffset, mp->m_da_node_ents, mp->m_maxicount,
mp->m_inoalign_mask);
kdb_printf("dir_node_ents %u attr_node_ents %u\n",
mp->m_dir_node_ents, mp->m_attr_node_ents);
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,
mp->m_resblks_avail);
#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