xfs: abstract the differences in dir2/dir3 via an ops vector
Lots of the dir code now goes through switches to determine what is the correct on-disk format to parse. It generally involves a "xfs_sbversion_hasfoo" check, deferencing the superblock version and feature fields and hence touching several cache lines per operation in the process. Some operations do multiple checks because they nest conditional operations and they don't pass the information in a direct fashion between each other. Hence, add an ops vector to the xfs_inode structure that is configured when the inode is initialised to point to all the correct decode and encoding operations. This will significantly reduce the branchiness and cacheline footprint of the directory object decoding and encoding. This is the first patch in a series of conversion patches. It will introduce the ops structure, the setup of it and add the first operation to the vector. Subsequent patches will convert directory ops one at a time to keep the changes simple and obvious. Just this patch shows the benefit of such an approach on code size. Just converting the two shortform dir operations as this patch does decreases the built binary size by ~1500 bytes: $ size fs/xfs/xfs.o.orig fs/xfs/xfs.o.p1 text data bss dec hex filename 794490 96802 1096 892388 d9de4 fs/xfs/xfs.o.orig 792986 96802 1096 890884 d9804 fs/xfs/xfs.o.p1 $ That's a significant decrease in the instruction cache footprint of the directory code for such a simple change, and indicates that this approach is definitely worth pursuing further. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Ben Myers <bpm@sgi.com>
This commit is contained in:
parent
c963c6193a
commit
32c5483a8a
12 changed files with 132 additions and 45 deletions
|
@ -66,6 +66,7 @@ xfs-y += xfs_alloc.o \
|
||||||
xfs_bmap_btree.o \
|
xfs_bmap_btree.o \
|
||||||
xfs_btree.o \
|
xfs_btree.o \
|
||||||
xfs_da_btree.o \
|
xfs_da_btree.o \
|
||||||
|
xfs_da_format.o \
|
||||||
xfs_dir2.o \
|
xfs_dir2.o \
|
||||||
xfs_dir2_block.o \
|
xfs_dir2_block.o \
|
||||||
xfs_dir2_data.o \
|
xfs_dir2_data.o \
|
||||||
|
|
|
@ -23,6 +23,7 @@ struct xfs_bmap_free;
|
||||||
struct xfs_inode;
|
struct xfs_inode;
|
||||||
struct xfs_trans;
|
struct xfs_trans;
|
||||||
struct zone;
|
struct zone;
|
||||||
|
struct xfs_dir_ops;
|
||||||
|
|
||||||
/*========================================================================
|
/*========================================================================
|
||||||
* Btree searching and modification structure definitions.
|
* Btree searching and modification structure definitions.
|
||||||
|
|
85
fs/xfs/xfs_da_format.c
Normal file
85
fs/xfs/xfs_da_format.c
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2000,2002,2005 Silicon Graphics, Inc.
|
||||||
|
* Copyright (c) 2013 Red Hat, Inc.
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it would be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
#include "xfs.h"
|
||||||
|
#include "xfs_fs.h"
|
||||||
|
#include "xfs_format.h"
|
||||||
|
#include "xfs_log_format.h"
|
||||||
|
#include "xfs_trans_resv.h"
|
||||||
|
#include "xfs_sb.h"
|
||||||
|
#include "xfs_ag.h"
|
||||||
|
#include "xfs_mount.h"
|
||||||
|
#include "xfs_da_format.h"
|
||||||
|
#include "xfs_inode.h"
|
||||||
|
#include "xfs_dir2.h"
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
xfs_dir2_sf_entsize(
|
||||||
|
struct xfs_dir2_sf_hdr *hdr,
|
||||||
|
int len)
|
||||||
|
{
|
||||||
|
int count = sizeof(struct xfs_dir2_sf_entry); /* namelen + offset */
|
||||||
|
|
||||||
|
count += len; /* name */
|
||||||
|
count += hdr->i8count ? sizeof(xfs_dir2_ino8_t) :
|
||||||
|
sizeof(xfs_dir2_ino4_t); /* ino # */
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
xfs_dir3_sf_entsize(
|
||||||
|
struct xfs_dir2_sf_hdr *hdr,
|
||||||
|
int len)
|
||||||
|
{
|
||||||
|
return xfs_dir2_sf_entsize(hdr, len) + sizeof(__uint8_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct xfs_dir2_sf_entry *
|
||||||
|
xfs_dir2_sf_nextentry(
|
||||||
|
struct xfs_dir2_sf_hdr *hdr,
|
||||||
|
struct xfs_dir2_sf_entry *sfep)
|
||||||
|
{
|
||||||
|
return (struct xfs_dir2_sf_entry *)
|
||||||
|
((char *)sfep + xfs_dir2_sf_entsize(hdr, sfep->namelen));
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct xfs_dir2_sf_entry *
|
||||||
|
xfs_dir3_sf_nextentry(
|
||||||
|
struct xfs_dir2_sf_hdr *hdr,
|
||||||
|
struct xfs_dir2_sf_entry *sfep)
|
||||||
|
{
|
||||||
|
return (struct xfs_dir2_sf_entry *)
|
||||||
|
((char *)sfep + xfs_dir3_sf_entsize(hdr, sfep->namelen));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const struct xfs_dir_ops xfs_dir2_ops = {
|
||||||
|
.sf_entsize = xfs_dir2_sf_entsize,
|
||||||
|
.sf_nextentry = xfs_dir2_sf_nextentry,
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct xfs_dir_ops xfs_dir2_ftype_ops = {
|
||||||
|
.sf_entsize = xfs_dir3_sf_entsize,
|
||||||
|
.sf_nextentry = xfs_dir3_sf_nextentry,
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct xfs_dir_ops xfs_dir3_ops = {
|
||||||
|
.sf_entsize = xfs_dir3_sf_entsize,
|
||||||
|
.sf_nextentry = xfs_dir3_sf_nextentry,
|
||||||
|
};
|
|
@ -329,32 +329,6 @@ xfs_dir2_sf_firstentry(struct xfs_dir2_sf_hdr *hdr)
|
||||||
((char *)hdr + xfs_dir2_sf_hdr_size(hdr->i8count));
|
((char *)hdr + xfs_dir2_sf_hdr_size(hdr->i8count));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
|
||||||
xfs_dir3_sf_entsize(
|
|
||||||
struct xfs_mount *mp,
|
|
||||||
struct xfs_dir2_sf_hdr *hdr,
|
|
||||||
int len)
|
|
||||||
{
|
|
||||||
int count = sizeof(struct xfs_dir2_sf_entry); /* namelen + offset */
|
|
||||||
|
|
||||||
count += len; /* name */
|
|
||||||
count += hdr->i8count ? sizeof(xfs_dir2_ino8_t) :
|
|
||||||
sizeof(xfs_dir2_ino4_t); /* ino # */
|
|
||||||
if (xfs_sb_version_hasftype(&mp->m_sb))
|
|
||||||
count += sizeof(__uint8_t); /* file type */
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline struct xfs_dir2_sf_entry *
|
|
||||||
xfs_dir3_sf_nextentry(
|
|
||||||
struct xfs_mount *mp,
|
|
||||||
struct xfs_dir2_sf_hdr *hdr,
|
|
||||||
struct xfs_dir2_sf_entry *sfep)
|
|
||||||
{
|
|
||||||
return (struct xfs_dir2_sf_entry *)
|
|
||||||
((char *)sfep + xfs_dir3_sf_entsize(mp, hdr, sfep->namelen));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* in dir3 shortform directories, the file type field is stored at a variable
|
* in dir3 shortform directories, the file type field is stored at a variable
|
||||||
* offset after the inode number. Because it's only a single byte, endian
|
* offset after the inode number. Because it's only a single byte, endian
|
||||||
|
|
|
@ -112,6 +112,13 @@ xfs_dir_mount(
|
||||||
mp->m_dirnameops = &xfs_ascii_ci_nameops;
|
mp->m_dirnameops = &xfs_ascii_ci_nameops;
|
||||||
else
|
else
|
||||||
mp->m_dirnameops = &xfs_default_nameops;
|
mp->m_dirnameops = &xfs_default_nameops;
|
||||||
|
|
||||||
|
if (xfs_sb_version_hascrc(&mp->m_sb))
|
||||||
|
mp->m_dir_inode_ops = &xfs_dir3_ops;
|
||||||
|
else if (xfs_sb_version_hasftype(&mp->m_sb))
|
||||||
|
mp->m_dir_inode_ops = &xfs_dir2_ftype_ops;
|
||||||
|
else
|
||||||
|
mp->m_dir_inode_ops = &xfs_dir2_ops;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -31,6 +31,20 @@ struct xfs_dir2_data_unused;
|
||||||
|
|
||||||
extern struct xfs_name xfs_name_dotdot;
|
extern struct xfs_name xfs_name_dotdot;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* directory operations vector for encode/decode routines
|
||||||
|
*/
|
||||||
|
struct xfs_dir_ops {
|
||||||
|
int (*sf_entsize)(struct xfs_dir2_sf_hdr *hdr, int len);
|
||||||
|
struct xfs_dir2_sf_entry *
|
||||||
|
(*sf_nextentry)(struct xfs_dir2_sf_hdr *hdr,
|
||||||
|
struct xfs_dir2_sf_entry *sfep);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const struct xfs_dir_ops xfs_dir2_ops;
|
||||||
|
extern const struct xfs_dir_ops xfs_dir2_ftype_ops;
|
||||||
|
extern const struct xfs_dir_ops xfs_dir3_ops;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generic directory interface routines
|
* Generic directory interface routines
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1240,7 +1240,7 @@ xfs_dir2_sf_to_block(
|
||||||
if (++i == sfp->count)
|
if (++i == sfp->count)
|
||||||
sfep = NULL;
|
sfep = NULL;
|
||||||
else
|
else
|
||||||
sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep);
|
sfep = dp->d_ops->sf_nextentry(sfp, sfep);
|
||||||
}
|
}
|
||||||
/* Done with the temporary buffer */
|
/* Done with the temporary buffer */
|
||||||
kmem_free(sfp);
|
kmem_free(sfp);
|
||||||
|
|
|
@ -153,7 +153,7 @@ xfs_dir2_sf_getdents(
|
||||||
xfs_dir2_sf_get_offset(sfep));
|
xfs_dir2_sf_get_offset(sfep));
|
||||||
|
|
||||||
if (ctx->pos > off) {
|
if (ctx->pos > off) {
|
||||||
sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep);
|
sfep = dp->d_ops->sf_nextentry(sfp, sfep);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,7 +163,7 @@ xfs_dir2_sf_getdents(
|
||||||
if (!dir_emit(ctx, (char *)sfep->name, sfep->namelen, ino,
|
if (!dir_emit(ctx, (char *)sfep->name, sfep->namelen, ino,
|
||||||
xfs_dir3_get_dtype(mp, filetype)))
|
xfs_dir3_get_dtype(mp, filetype)))
|
||||||
return 0;
|
return 0;
|
||||||
sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep);
|
sfep = dp->d_ops->sf_nextentry(sfp, sfep);
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->pos = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0) &
|
ctx->pos = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0) &
|
||||||
|
|
|
@ -336,7 +336,7 @@ xfs_dir2_block_to_sf(
|
||||||
xfs_dir3_sfe_put_ftype(mp, sfp, sfep,
|
xfs_dir3_sfe_put_ftype(mp, sfp, sfep,
|
||||||
xfs_dir3_dirent_get_ftype(mp, dep));
|
xfs_dir3_dirent_get_ftype(mp, dep));
|
||||||
|
|
||||||
sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep);
|
sfep = dp->d_ops->sf_nextentry(sfp, sfep);
|
||||||
}
|
}
|
||||||
ptr += xfs_dir3_data_entsize(mp, dep->namelen);
|
ptr += xfs_dir3_data_entsize(mp, dep->namelen);
|
||||||
}
|
}
|
||||||
|
@ -389,7 +389,7 @@ xfs_dir2_sf_addname(
|
||||||
/*
|
/*
|
||||||
* Compute entry (and change in) size.
|
* Compute entry (and change in) size.
|
||||||
*/
|
*/
|
||||||
add_entsize = xfs_dir3_sf_entsize(dp->i_mount, sfp, args->namelen);
|
add_entsize = dp->d_ops->sf_entsize(sfp, args->namelen);
|
||||||
incr_isize = add_entsize;
|
incr_isize = add_entsize;
|
||||||
objchange = 0;
|
objchange = 0;
|
||||||
#if XFS_BIG_INUMS
|
#if XFS_BIG_INUMS
|
||||||
|
@ -483,8 +483,7 @@ xfs_dir2_sf_addname_easy(
|
||||||
/*
|
/*
|
||||||
* Grow the in-inode space.
|
* Grow the in-inode space.
|
||||||
*/
|
*/
|
||||||
xfs_idata_realloc(dp,
|
xfs_idata_realloc(dp, dp->d_ops->sf_entsize(sfp, args->namelen),
|
||||||
xfs_dir3_sf_entsize(dp->i_mount, sfp, args->namelen),
|
|
||||||
XFS_DATA_FORK);
|
XFS_DATA_FORK);
|
||||||
/*
|
/*
|
||||||
* Need to set up again due to realloc of the inode data.
|
* Need to set up again due to realloc of the inode data.
|
||||||
|
@ -563,7 +562,7 @@ xfs_dir2_sf_addname_hard(
|
||||||
eof = (char *)oldsfep == &buf[old_isize];
|
eof = (char *)oldsfep == &buf[old_isize];
|
||||||
!eof;
|
!eof;
|
||||||
offset = new_offset + xfs_dir3_data_entsize(mp, oldsfep->namelen),
|
offset = new_offset + xfs_dir3_data_entsize(mp, oldsfep->namelen),
|
||||||
oldsfep = xfs_dir3_sf_nextentry(mp, oldsfp, oldsfep),
|
oldsfep = dp->d_ops->sf_nextentry(oldsfp, oldsfep),
|
||||||
eof = (char *)oldsfep == &buf[old_isize]) {
|
eof = (char *)oldsfep == &buf[old_isize]) {
|
||||||
new_offset = xfs_dir2_sf_get_offset(oldsfep);
|
new_offset = xfs_dir2_sf_get_offset(oldsfep);
|
||||||
if (offset + add_datasize <= new_offset)
|
if (offset + add_datasize <= new_offset)
|
||||||
|
@ -603,7 +602,7 @@ xfs_dir2_sf_addname_hard(
|
||||||
* If there's more left to copy, do that.
|
* If there's more left to copy, do that.
|
||||||
*/
|
*/
|
||||||
if (!eof) {
|
if (!eof) {
|
||||||
sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep);
|
sfep = dp->d_ops->sf_nextentry(sfp, sfep);
|
||||||
memcpy(sfep, oldsfep, old_isize - nbytes);
|
memcpy(sfep, oldsfep, old_isize - nbytes);
|
||||||
}
|
}
|
||||||
kmem_free(buf);
|
kmem_free(buf);
|
||||||
|
@ -653,7 +652,7 @@ xfs_dir2_sf_addname_pick(
|
||||||
holefit = offset + size <= xfs_dir2_sf_get_offset(sfep);
|
holefit = offset + size <= xfs_dir2_sf_get_offset(sfep);
|
||||||
offset = xfs_dir2_sf_get_offset(sfep) +
|
offset = xfs_dir2_sf_get_offset(sfep) +
|
||||||
xfs_dir3_data_entsize(mp, sfep->namelen);
|
xfs_dir3_data_entsize(mp, sfep->namelen);
|
||||||
sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep);
|
sfep = dp->d_ops->sf_nextentry(sfp, sfep);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Calculate data bytes used excluding the new entry, if this
|
* Calculate data bytes used excluding the new entry, if this
|
||||||
|
@ -719,7 +718,7 @@ xfs_dir2_sf_check(
|
||||||
|
|
||||||
for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp);
|
for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp);
|
||||||
i < sfp->count;
|
i < sfp->count;
|
||||||
i++, sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep)) {
|
i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep)) {
|
||||||
ASSERT(xfs_dir2_sf_get_offset(sfep) >= offset);
|
ASSERT(xfs_dir2_sf_get_offset(sfep) >= offset);
|
||||||
ino = xfs_dir3_sfe_get_ino(mp, sfp, sfep);
|
ino = xfs_dir3_sfe_get_ino(mp, sfp, sfep);
|
||||||
i8count += ino > XFS_DIR2_MAX_SHORT_INUM;
|
i8count += ino > XFS_DIR2_MAX_SHORT_INUM;
|
||||||
|
@ -848,7 +847,7 @@ xfs_dir2_sf_lookup(
|
||||||
*/
|
*/
|
||||||
ci_sfep = NULL;
|
ci_sfep = NULL;
|
||||||
for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->count;
|
for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->count;
|
||||||
i++, sfep = xfs_dir3_sf_nextentry(dp->i_mount, sfp, sfep)) {
|
i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep)) {
|
||||||
/*
|
/*
|
||||||
* Compare name and if it's an exact match, return the inode
|
* Compare name and if it's an exact match, return the inode
|
||||||
* number. If it's the first case-insensitive match, store the
|
* number. If it's the first case-insensitive match, store the
|
||||||
|
@ -917,7 +916,7 @@ xfs_dir2_sf_removename(
|
||||||
* Find the one we're deleting.
|
* Find the one we're deleting.
|
||||||
*/
|
*/
|
||||||
for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->count;
|
for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->count;
|
||||||
i++, sfep = xfs_dir3_sf_nextentry(dp->i_mount, sfp, sfep)) {
|
i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep)) {
|
||||||
if (xfs_da_compname(args, sfep->name, sfep->namelen) ==
|
if (xfs_da_compname(args, sfep->name, sfep->namelen) ==
|
||||||
XFS_CMP_EXACT) {
|
XFS_CMP_EXACT) {
|
||||||
ASSERT(xfs_dir3_sfe_get_ino(dp->i_mount, sfp, sfep) ==
|
ASSERT(xfs_dir3_sfe_get_ino(dp->i_mount, sfp, sfep) ==
|
||||||
|
@ -934,7 +933,7 @@ xfs_dir2_sf_removename(
|
||||||
* Calculate sizes.
|
* Calculate sizes.
|
||||||
*/
|
*/
|
||||||
byteoff = (int)((char *)sfep - (char *)sfp);
|
byteoff = (int)((char *)sfep - (char *)sfp);
|
||||||
entsize = xfs_dir3_sf_entsize(dp->i_mount, sfp, args->namelen);
|
entsize = dp->d_ops->sf_entsize(sfp, args->namelen);
|
||||||
newsize = oldsize - entsize;
|
newsize = oldsize - entsize;
|
||||||
/*
|
/*
|
||||||
* Copy the part if any after the removed entry, sliding it down.
|
* Copy the part if any after the removed entry, sliding it down.
|
||||||
|
@ -1051,7 +1050,7 @@ xfs_dir2_sf_replace(
|
||||||
*/
|
*/
|
||||||
else {
|
else {
|
||||||
for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->count;
|
for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->count;
|
||||||
i++, sfep = xfs_dir3_sf_nextentry(dp->i_mount, sfp, sfep)) {
|
i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep)) {
|
||||||
if (xfs_da_compname(args, sfep->name, sfep->namelen) ==
|
if (xfs_da_compname(args, sfep->name, sfep->namelen) ==
|
||||||
XFS_CMP_EXACT) {
|
XFS_CMP_EXACT) {
|
||||||
#if XFS_BIG_INUMS || defined(DEBUG)
|
#if XFS_BIG_INUMS || defined(DEBUG)
|
||||||
|
@ -1172,8 +1171,8 @@ xfs_dir2_sf_toino4(
|
||||||
for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp),
|
for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp),
|
||||||
oldsfep = xfs_dir2_sf_firstentry(oldsfp);
|
oldsfep = xfs_dir2_sf_firstentry(oldsfp);
|
||||||
i < sfp->count;
|
i < sfp->count;
|
||||||
i++, sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep),
|
i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep),
|
||||||
oldsfep = xfs_dir3_sf_nextentry(mp, oldsfp, oldsfep)) {
|
oldsfep = dp->d_ops->sf_nextentry(oldsfp, oldsfep)) {
|
||||||
sfep->namelen = oldsfep->namelen;
|
sfep->namelen = oldsfep->namelen;
|
||||||
sfep->offset = oldsfep->offset;
|
sfep->offset = oldsfep->offset;
|
||||||
memcpy(sfep->name, oldsfep->name, sfep->namelen);
|
memcpy(sfep->name, oldsfep->name, sfep->namelen);
|
||||||
|
@ -1251,8 +1250,8 @@ xfs_dir2_sf_toino8(
|
||||||
for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp),
|
for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp),
|
||||||
oldsfep = xfs_dir2_sf_firstentry(oldsfp);
|
oldsfep = xfs_dir2_sf_firstentry(oldsfp);
|
||||||
i < sfp->count;
|
i < sfp->count;
|
||||||
i++, sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep),
|
i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep),
|
||||||
oldsfep = xfs_dir3_sf_nextentry(mp, oldsfp, oldsfep)) {
|
oldsfep = dp->d_ops->sf_nextentry(oldsfp, oldsfep)) {
|
||||||
sfep->namelen = oldsfep->namelen;
|
sfep->namelen = oldsfep->namelen;
|
||||||
sfep->offset = oldsfep->offset;
|
sfep->offset = oldsfep->offset;
|
||||||
memcpy(sfep->name, oldsfep->name, sfep->namelen);
|
memcpy(sfep->name, oldsfep->name, sfep->namelen);
|
||||||
|
|
|
@ -49,6 +49,9 @@ typedef struct xfs_inode {
|
||||||
xfs_ifork_t *i_afp; /* attribute fork pointer */
|
xfs_ifork_t *i_afp; /* attribute fork pointer */
|
||||||
xfs_ifork_t i_df; /* data fork */
|
xfs_ifork_t i_df; /* data fork */
|
||||||
|
|
||||||
|
/* operations vectors */
|
||||||
|
const struct xfs_dir_ops *d_ops; /* directory ops vector */
|
||||||
|
|
||||||
/* Transaction and locking information. */
|
/* Transaction and locking information. */
|
||||||
struct xfs_inode_log_item *i_itemp; /* logging information */
|
struct xfs_inode_log_item *i_itemp; /* logging information */
|
||||||
mrlock_t i_lock; /* inode lock */
|
mrlock_t i_lock; /* inode lock */
|
||||||
|
|
|
@ -1215,6 +1215,7 @@ xfs_setup_inode(
|
||||||
else
|
else
|
||||||
inode->i_op = &xfs_dir_inode_operations;
|
inode->i_op = &xfs_dir_inode_operations;
|
||||||
inode->i_fop = &xfs_dir_file_operations;
|
inode->i_fop = &xfs_dir_file_operations;
|
||||||
|
ip->d_ops = ip->i_mount->m_dir_inode_ops;
|
||||||
break;
|
break;
|
||||||
case S_IFLNK:
|
case S_IFLNK:
|
||||||
inode->i_op = &xfs_symlink_inode_operations;
|
inode->i_op = &xfs_symlink_inode_operations;
|
||||||
|
|
|
@ -26,6 +26,7 @@ struct xfs_mru_cache;
|
||||||
struct xfs_nameops;
|
struct xfs_nameops;
|
||||||
struct xfs_ail;
|
struct xfs_ail;
|
||||||
struct xfs_quotainfo;
|
struct xfs_quotainfo;
|
||||||
|
struct xfs_dir_ops;
|
||||||
|
|
||||||
#ifdef HAVE_PERCPU_SB
|
#ifdef HAVE_PERCPU_SB
|
||||||
|
|
||||||
|
@ -148,6 +149,7 @@ typedef struct xfs_mount {
|
||||||
int m_dir_magicpct; /* 37% of the dir blocksize */
|
int m_dir_magicpct; /* 37% of the dir blocksize */
|
||||||
__uint8_t m_sectbb_log; /* sectlog - BBSHIFT */
|
__uint8_t m_sectbb_log; /* sectlog - BBSHIFT */
|
||||||
const struct xfs_nameops *m_dirnameops; /* vector of dir name ops */
|
const struct xfs_nameops *m_dirnameops; /* vector of dir name ops */
|
||||||
|
const struct xfs_dir_ops *m_dir_inode_ops; /* vector of dir inode ops */
|
||||||
int m_dirblksize; /* directory block sz--bytes */
|
int m_dirblksize; /* directory block sz--bytes */
|
||||||
int m_dirblkfsbs; /* directory block sz--fsbs */
|
int m_dirblkfsbs; /* directory block sz--fsbs */
|
||||||
xfs_dablk_t m_dirdatablk; /* blockno of dir data v2 */
|
xfs_dablk_t m_dirdatablk; /* blockno of dir data v2 */
|
||||||
|
|
Loading…
Reference in a new issue