4141956ae0
Next step in the vectorisation process is the leaf block encode/decode operations. Most of the operations on leaves are handled by the data block vectors, so there are relatively few of them here. Because of all the shuffling of code and having to pass more state to some functions, this patch doesn't directly reduce the size of the binary. It does open up many more opportunities for factoring and optimisation, however. 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 792350 96802 1096 890248 d9588 fs/xfs/xfs.o.p2 789293 96802 1096 887191 d8997 fs/xfs/xfs.o.p3 789005 96802 1096 886903 d8997 fs/xfs/xfs.o.p4 789061 96802 1096 886959 d88af fs/xfs/xfs.o.p5 Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Ben Myers <bpm@sgi.com>
596 lines
14 KiB
C
596 lines
14 KiB
C
/*
|
|
* 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"
|
|
|
|
/*
|
|
* Shortform directory ops
|
|
*/
|
|
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));
|
|
}
|
|
|
|
|
|
/*
|
|
* For filetype enabled shortform directories, the file type field is stored at
|
|
* the end of the name. Because it's only a single byte, endian conversion is
|
|
* not necessary. For non-filetype enable directories, the type is always
|
|
* unknown and we never store the value.
|
|
*/
|
|
static __uint8_t
|
|
xfs_dir2_sfe_get_ftype(
|
|
struct xfs_dir2_sf_entry *sfep)
|
|
{
|
|
return XFS_DIR3_FT_UNKNOWN;
|
|
}
|
|
|
|
static void
|
|
xfs_dir2_sfe_put_ftype(
|
|
struct xfs_dir2_sf_entry *sfep,
|
|
__uint8_t ftype)
|
|
{
|
|
ASSERT(ftype < XFS_DIR3_FT_MAX);
|
|
}
|
|
|
|
static __uint8_t
|
|
xfs_dir3_sfe_get_ftype(
|
|
struct xfs_dir2_sf_entry *sfep)
|
|
{
|
|
__uint8_t ftype;
|
|
|
|
ftype = sfep->name[sfep->namelen];
|
|
if (ftype >= XFS_DIR3_FT_MAX)
|
|
return XFS_DIR3_FT_UNKNOWN;
|
|
return ftype;
|
|
}
|
|
|
|
static void
|
|
xfs_dir3_sfe_put_ftype(
|
|
struct xfs_dir2_sf_entry *sfep,
|
|
__uint8_t ftype)
|
|
{
|
|
ASSERT(ftype < XFS_DIR3_FT_MAX);
|
|
|
|
sfep->name[sfep->namelen] = ftype;
|
|
}
|
|
|
|
/*
|
|
* Inode numbers in short-form directories can come in two versions,
|
|
* either 4 bytes or 8 bytes wide. These helpers deal with the
|
|
* two forms transparently by looking at the headers i8count field.
|
|
*
|
|
* For 64-bit inode number the most significant byte must be zero.
|
|
*/
|
|
static xfs_ino_t
|
|
xfs_dir2_sf_get_ino(
|
|
struct xfs_dir2_sf_hdr *hdr,
|
|
xfs_dir2_inou_t *from)
|
|
{
|
|
if (hdr->i8count)
|
|
return get_unaligned_be64(&from->i8.i) & 0x00ffffffffffffffULL;
|
|
else
|
|
return get_unaligned_be32(&from->i4.i);
|
|
}
|
|
|
|
static void
|
|
xfs_dir2_sf_put_ino(
|
|
struct xfs_dir2_sf_hdr *hdr,
|
|
xfs_dir2_inou_t *to,
|
|
xfs_ino_t ino)
|
|
{
|
|
ASSERT((ino & 0xff00000000000000ULL) == 0);
|
|
|
|
if (hdr->i8count)
|
|
put_unaligned_be64(ino, &to->i8.i);
|
|
else
|
|
put_unaligned_be32(ino, &to->i4.i);
|
|
}
|
|
|
|
static xfs_ino_t
|
|
xfs_dir2_sf_get_parent_ino(
|
|
struct xfs_dir2_sf_hdr *hdr)
|
|
{
|
|
return xfs_dir2_sf_get_ino(hdr, &hdr->parent);
|
|
}
|
|
|
|
static void
|
|
xfs_dir2_sf_put_parent_ino(
|
|
struct xfs_dir2_sf_hdr *hdr,
|
|
xfs_ino_t ino)
|
|
{
|
|
xfs_dir2_sf_put_ino(hdr, &hdr->parent, ino);
|
|
}
|
|
|
|
/*
|
|
* In short-form directory entries the inode numbers are stored at variable
|
|
* offset behind the entry name. If the entry stores a filetype value, then it
|
|
* sits between the name and the inode number. Hence the inode numbers may only
|
|
* be accessed through the helpers below.
|
|
*/
|
|
static xfs_ino_t
|
|
xfs_dir2_sfe_get_ino(
|
|
struct xfs_dir2_sf_hdr *hdr,
|
|
struct xfs_dir2_sf_entry *sfep)
|
|
{
|
|
return xfs_dir2_sf_get_ino(hdr,
|
|
(xfs_dir2_inou_t *)&sfep->name[sfep->namelen]);
|
|
}
|
|
|
|
static void
|
|
xfs_dir2_sfe_put_ino(
|
|
struct xfs_dir2_sf_hdr *hdr,
|
|
struct xfs_dir2_sf_entry *sfep,
|
|
xfs_ino_t ino)
|
|
{
|
|
xfs_dir2_sf_put_ino(hdr,
|
|
(xfs_dir2_inou_t *)&sfep->name[sfep->namelen], ino);
|
|
}
|
|
|
|
static xfs_ino_t
|
|
xfs_dir3_sfe_get_ino(
|
|
struct xfs_dir2_sf_hdr *hdr,
|
|
struct xfs_dir2_sf_entry *sfep)
|
|
{
|
|
return xfs_dir2_sf_get_ino(hdr,
|
|
(xfs_dir2_inou_t *)&sfep->name[sfep->namelen + 1]);
|
|
}
|
|
|
|
static void
|
|
xfs_dir3_sfe_put_ino(
|
|
struct xfs_dir2_sf_hdr *hdr,
|
|
struct xfs_dir2_sf_entry *sfep,
|
|
xfs_ino_t ino)
|
|
{
|
|
xfs_dir2_sf_put_ino(hdr,
|
|
(xfs_dir2_inou_t *)&sfep->name[sfep->namelen + 1], ino);
|
|
}
|
|
|
|
|
|
/*
|
|
* Directory data block operations
|
|
*/
|
|
static int
|
|
__xfs_dir3_data_entsize(
|
|
bool ftype,
|
|
int n)
|
|
{
|
|
int size = offsetof(struct xfs_dir2_data_entry, name[0]);
|
|
|
|
size += n;
|
|
size += sizeof(xfs_dir2_data_off_t);
|
|
if (ftype)
|
|
size += sizeof(__uint8_t);
|
|
return roundup(size, XFS_DIR2_DATA_ALIGN);
|
|
}
|
|
|
|
static int
|
|
xfs_dir2_data_entsize(
|
|
int n)
|
|
{
|
|
return __xfs_dir3_data_entsize(false, n);
|
|
}
|
|
static int
|
|
xfs_dir3_data_entsize(
|
|
int n)
|
|
{
|
|
return __xfs_dir3_data_entsize(true, n);
|
|
}
|
|
|
|
static __uint8_t
|
|
xfs_dir2_data_get_ftype(
|
|
struct xfs_dir2_data_entry *dep)
|
|
{
|
|
return XFS_DIR3_FT_UNKNOWN;
|
|
}
|
|
|
|
static void
|
|
xfs_dir2_data_put_ftype(
|
|
struct xfs_dir2_data_entry *dep,
|
|
__uint8_t ftype)
|
|
{
|
|
ASSERT(ftype < XFS_DIR3_FT_MAX);
|
|
}
|
|
|
|
static __uint8_t
|
|
xfs_dir3_data_get_ftype(
|
|
struct xfs_dir2_data_entry *dep)
|
|
{
|
|
__uint8_t ftype = dep->name[dep->namelen];
|
|
|
|
ASSERT(ftype < XFS_DIR3_FT_MAX);
|
|
if (ftype >= XFS_DIR3_FT_MAX)
|
|
return XFS_DIR3_FT_UNKNOWN;
|
|
return ftype;
|
|
}
|
|
|
|
static void
|
|
xfs_dir3_data_put_ftype(
|
|
struct xfs_dir2_data_entry *dep,
|
|
__uint8_t type)
|
|
{
|
|
ASSERT(type < XFS_DIR3_FT_MAX);
|
|
ASSERT(dep->namelen != 0);
|
|
|
|
dep->name[dep->namelen] = type;
|
|
}
|
|
|
|
/*
|
|
* Pointer to an entry's tag word.
|
|
*/
|
|
static __be16 *
|
|
xfs_dir2_data_entry_tag_p(
|
|
struct xfs_dir2_data_entry *dep)
|
|
{
|
|
return (__be16 *)((char *)dep +
|
|
xfs_dir2_data_entsize(dep->namelen) - sizeof(__be16));
|
|
}
|
|
|
|
static __be16 *
|
|
xfs_dir3_data_entry_tag_p(
|
|
struct xfs_dir2_data_entry *dep)
|
|
{
|
|
return (__be16 *)((char *)dep +
|
|
xfs_dir3_data_entsize(dep->namelen) - sizeof(__be16));
|
|
}
|
|
|
|
/*
|
|
* Offsets of . and .. in data space (always block 0)
|
|
*/
|
|
static xfs_dir2_data_aoff_t
|
|
xfs_dir2_data_dot_offset(void)
|
|
{
|
|
return sizeof(struct xfs_dir2_data_hdr);
|
|
}
|
|
|
|
static xfs_dir2_data_aoff_t
|
|
xfs_dir2_data_dotdot_offset(void)
|
|
{
|
|
return xfs_dir2_data_dot_offset() + xfs_dir2_data_entsize(1);
|
|
}
|
|
|
|
static xfs_dir2_data_aoff_t
|
|
xfs_dir2_data_first_offset(void)
|
|
{
|
|
return xfs_dir2_data_dotdot_offset() + xfs_dir2_data_entsize(2);
|
|
}
|
|
|
|
static xfs_dir2_data_aoff_t
|
|
xfs_dir3_data_dot_offset(void)
|
|
{
|
|
return sizeof(struct xfs_dir3_data_hdr);
|
|
}
|
|
|
|
static xfs_dir2_data_aoff_t
|
|
xfs_dir3_data_dotdot_offset(void)
|
|
{
|
|
return xfs_dir3_data_dot_offset() + xfs_dir3_data_entsize(1);
|
|
}
|
|
|
|
static xfs_dir2_data_aoff_t
|
|
xfs_dir3_data_first_offset(void)
|
|
{
|
|
return xfs_dir3_data_dotdot_offset() + xfs_dir3_data_entsize(2);
|
|
}
|
|
|
|
/*
|
|
* location of . and .. in data space (always block 0)
|
|
*/
|
|
static struct xfs_dir2_data_entry *
|
|
xfs_dir2_data_dot_entry_p(
|
|
struct xfs_dir2_data_hdr *hdr)
|
|
{
|
|
return (struct xfs_dir2_data_entry *)
|
|
((char *)hdr + xfs_dir2_data_dot_offset());
|
|
}
|
|
|
|
static struct xfs_dir2_data_entry *
|
|
xfs_dir2_data_dotdot_entry_p(
|
|
struct xfs_dir2_data_hdr *hdr)
|
|
{
|
|
return (struct xfs_dir2_data_entry *)
|
|
((char *)hdr + xfs_dir2_data_dotdot_offset());
|
|
}
|
|
|
|
static struct xfs_dir2_data_entry *
|
|
xfs_dir2_data_first_entry_p(
|
|
struct xfs_dir2_data_hdr *hdr)
|
|
{
|
|
return (struct xfs_dir2_data_entry *)
|
|
((char *)hdr + xfs_dir2_data_first_offset());
|
|
}
|
|
|
|
static struct xfs_dir2_data_entry *
|
|
xfs_dir3_data_dot_entry_p(
|
|
struct xfs_dir2_data_hdr *hdr)
|
|
{
|
|
return (struct xfs_dir2_data_entry *)
|
|
((char *)hdr + xfs_dir3_data_dot_offset());
|
|
}
|
|
|
|
static struct xfs_dir2_data_entry *
|
|
xfs_dir3_data_dotdot_entry_p(
|
|
struct xfs_dir2_data_hdr *hdr)
|
|
{
|
|
return (struct xfs_dir2_data_entry *)
|
|
((char *)hdr + xfs_dir3_data_dotdot_offset());
|
|
}
|
|
|
|
static struct xfs_dir2_data_entry *
|
|
xfs_dir3_data_first_entry_p(
|
|
struct xfs_dir2_data_hdr *hdr)
|
|
{
|
|
return (struct xfs_dir2_data_entry *)
|
|
((char *)hdr + xfs_dir3_data_first_offset());
|
|
}
|
|
|
|
static struct xfs_dir2_data_free *
|
|
xfs_dir2_data_bestfree_p(struct xfs_dir2_data_hdr *hdr)
|
|
{
|
|
return hdr->bestfree;
|
|
}
|
|
|
|
static struct xfs_dir2_data_free *
|
|
xfs_dir3_data_bestfree_p(struct xfs_dir2_data_hdr *hdr)
|
|
{
|
|
return ((struct xfs_dir3_data_hdr *)hdr)->best_free;
|
|
}
|
|
|
|
static size_t
|
|
xfs_dir2_data_entry_offset(void)
|
|
{
|
|
return sizeof(struct xfs_dir2_data_hdr);
|
|
}
|
|
|
|
static struct xfs_dir2_data_entry *
|
|
xfs_dir2_data_entry_p(struct xfs_dir2_data_hdr *hdr)
|
|
{
|
|
return (struct xfs_dir2_data_entry *)
|
|
((char *)hdr + xfs_dir2_data_entry_offset());
|
|
}
|
|
|
|
static struct xfs_dir2_data_unused *
|
|
xfs_dir2_data_unused_p(struct xfs_dir2_data_hdr *hdr)
|
|
{
|
|
return (struct xfs_dir2_data_unused *)
|
|
((char *)hdr + xfs_dir2_data_entry_offset());
|
|
}
|
|
|
|
static size_t
|
|
xfs_dir3_data_entry_offset(void)
|
|
{
|
|
return sizeof(struct xfs_dir3_data_hdr);
|
|
}
|
|
|
|
static struct xfs_dir2_data_entry *
|
|
xfs_dir3_data_entry_p(struct xfs_dir2_data_hdr *hdr)
|
|
{
|
|
return (struct xfs_dir2_data_entry *)
|
|
((char *)hdr + xfs_dir3_data_entry_offset());
|
|
}
|
|
|
|
static struct xfs_dir2_data_unused *
|
|
xfs_dir3_data_unused_p(struct xfs_dir2_data_hdr *hdr)
|
|
{
|
|
return (struct xfs_dir2_data_unused *)
|
|
((char *)hdr + xfs_dir3_data_entry_offset());
|
|
}
|
|
|
|
|
|
/*
|
|
* Directory Leaf block operations
|
|
*/
|
|
static int
|
|
xfs_dir2_leaf_hdr_size(void)
|
|
{
|
|
return sizeof(struct xfs_dir2_leaf_hdr);
|
|
}
|
|
|
|
static int
|
|
xfs_dir2_max_leaf_ents(struct xfs_mount *mp)
|
|
{
|
|
return (mp->m_dirblksize - xfs_dir2_leaf_hdr_size()) /
|
|
(uint)sizeof(struct xfs_dir2_leaf_entry);
|
|
}
|
|
|
|
static struct xfs_dir2_leaf_entry *
|
|
xfs_dir2_leaf_ents_p(struct xfs_dir2_leaf *lp)
|
|
{
|
|
return lp->__ents;
|
|
}
|
|
|
|
static int
|
|
xfs_dir3_leaf_hdr_size(void)
|
|
{
|
|
return sizeof(struct xfs_dir3_leaf_hdr);
|
|
}
|
|
|
|
static inline int
|
|
xfs_dir3_max_leaf_ents(struct xfs_mount *mp)
|
|
{
|
|
return (mp->m_dirblksize - xfs_dir3_leaf_hdr_size()) /
|
|
(uint)sizeof(struct xfs_dir2_leaf_entry);
|
|
}
|
|
|
|
static inline struct xfs_dir2_leaf_entry *
|
|
xfs_dir3_leaf_ents_p(struct xfs_dir2_leaf *lp)
|
|
{
|
|
return ((struct xfs_dir3_leaf *)lp)->__ents;
|
|
}
|
|
|
|
const struct xfs_dir_ops xfs_dir2_ops = {
|
|
.sf_entsize = xfs_dir2_sf_entsize,
|
|
.sf_nextentry = xfs_dir2_sf_nextentry,
|
|
.sf_get_ftype = xfs_dir2_sfe_get_ftype,
|
|
.sf_put_ftype = xfs_dir2_sfe_put_ftype,
|
|
.sf_get_ino = xfs_dir2_sfe_get_ino,
|
|
.sf_put_ino = xfs_dir2_sfe_put_ino,
|
|
.sf_get_parent_ino = xfs_dir2_sf_get_parent_ino,
|
|
.sf_put_parent_ino = xfs_dir2_sf_put_parent_ino,
|
|
|
|
.data_entsize = xfs_dir2_data_entsize,
|
|
.data_get_ftype = xfs_dir2_data_get_ftype,
|
|
.data_put_ftype = xfs_dir2_data_put_ftype,
|
|
.data_entry_tag_p = xfs_dir2_data_entry_tag_p,
|
|
.data_bestfree_p = xfs_dir2_data_bestfree_p,
|
|
|
|
.data_dot_offset = xfs_dir2_data_dot_offset,
|
|
.data_dotdot_offset = xfs_dir2_data_dotdot_offset,
|
|
.data_first_offset = xfs_dir2_data_first_offset,
|
|
.data_entry_offset = xfs_dir2_data_entry_offset,
|
|
|
|
.data_dot_entry_p = xfs_dir2_data_dot_entry_p,
|
|
.data_dotdot_entry_p = xfs_dir2_data_dotdot_entry_p,
|
|
.data_first_entry_p = xfs_dir2_data_first_entry_p,
|
|
.data_entry_p = xfs_dir2_data_entry_p,
|
|
.data_unused_p = xfs_dir2_data_unused_p,
|
|
|
|
.leaf_hdr_size = xfs_dir2_leaf_hdr_size,
|
|
.leaf_max_ents = xfs_dir2_max_leaf_ents,
|
|
.leaf_ents_p = xfs_dir2_leaf_ents_p,
|
|
|
|
};
|
|
|
|
const struct xfs_dir_ops xfs_dir2_ftype_ops = {
|
|
.sf_entsize = xfs_dir3_sf_entsize,
|
|
.sf_nextentry = xfs_dir3_sf_nextentry,
|
|
.sf_get_ftype = xfs_dir3_sfe_get_ftype,
|
|
.sf_put_ftype = xfs_dir3_sfe_put_ftype,
|
|
.sf_get_ino = xfs_dir3_sfe_get_ino,
|
|
.sf_put_ino = xfs_dir3_sfe_put_ino,
|
|
.sf_get_parent_ino = xfs_dir2_sf_get_parent_ino,
|
|
.sf_put_parent_ino = xfs_dir2_sf_put_parent_ino,
|
|
|
|
.data_entsize = xfs_dir3_data_entsize,
|
|
.data_get_ftype = xfs_dir3_data_get_ftype,
|
|
.data_put_ftype = xfs_dir3_data_put_ftype,
|
|
.data_entry_tag_p = xfs_dir3_data_entry_tag_p,
|
|
.data_bestfree_p = xfs_dir2_data_bestfree_p,
|
|
|
|
.data_dot_offset = xfs_dir2_data_dot_offset,
|
|
.data_dotdot_offset = xfs_dir2_data_dotdot_offset,
|
|
.data_first_offset = xfs_dir2_data_first_offset,
|
|
.data_entry_offset = xfs_dir2_data_entry_offset,
|
|
|
|
.data_dot_entry_p = xfs_dir2_data_dot_entry_p,
|
|
.data_dotdot_entry_p = xfs_dir2_data_dotdot_entry_p,
|
|
.data_first_entry_p = xfs_dir2_data_first_entry_p,
|
|
.data_entry_p = xfs_dir2_data_entry_p,
|
|
.data_unused_p = xfs_dir2_data_unused_p,
|
|
|
|
.leaf_hdr_size = xfs_dir2_leaf_hdr_size,
|
|
.leaf_max_ents = xfs_dir2_max_leaf_ents,
|
|
.leaf_ents_p = xfs_dir2_leaf_ents_p,
|
|
};
|
|
|
|
const struct xfs_dir_ops xfs_dir3_ops = {
|
|
.sf_entsize = xfs_dir3_sf_entsize,
|
|
.sf_nextentry = xfs_dir3_sf_nextentry,
|
|
.sf_get_ftype = xfs_dir3_sfe_get_ftype,
|
|
.sf_put_ftype = xfs_dir3_sfe_put_ftype,
|
|
.sf_get_ino = xfs_dir3_sfe_get_ino,
|
|
.sf_put_ino = xfs_dir3_sfe_put_ino,
|
|
.sf_get_parent_ino = xfs_dir2_sf_get_parent_ino,
|
|
.sf_put_parent_ino = xfs_dir2_sf_put_parent_ino,
|
|
|
|
.data_entsize = xfs_dir3_data_entsize,
|
|
.data_get_ftype = xfs_dir3_data_get_ftype,
|
|
.data_put_ftype = xfs_dir3_data_put_ftype,
|
|
.data_entry_tag_p = xfs_dir3_data_entry_tag_p,
|
|
.data_bestfree_p = xfs_dir3_data_bestfree_p,
|
|
|
|
.data_dot_offset = xfs_dir3_data_dot_offset,
|
|
.data_dotdot_offset = xfs_dir3_data_dotdot_offset,
|
|
.data_first_offset = xfs_dir3_data_first_offset,
|
|
.data_entry_offset = xfs_dir3_data_entry_offset,
|
|
|
|
.data_dot_entry_p = xfs_dir3_data_dot_entry_p,
|
|
.data_dotdot_entry_p = xfs_dir3_data_dotdot_entry_p,
|
|
.data_first_entry_p = xfs_dir3_data_first_entry_p,
|
|
.data_entry_p = xfs_dir3_data_entry_p,
|
|
.data_unused_p = xfs_dir3_data_unused_p,
|
|
|
|
.leaf_hdr_size = xfs_dir3_leaf_hdr_size,
|
|
.leaf_max_ents = xfs_dir3_max_leaf_ents,
|
|
.leaf_ents_p = xfs_dir3_leaf_ents_p,
|
|
};
|
|
|
|
/*
|
|
* Return the ops structure according to the current config. If we are passed
|
|
* an inode, then that overrides the default config we use which is based on
|
|
* feature bits.
|
|
*/
|
|
const struct xfs_dir_ops *
|
|
xfs_dir_get_ops(
|
|
struct xfs_mount *mp,
|
|
struct xfs_inode *dp)
|
|
{
|
|
if (dp)
|
|
return dp->d_ops;
|
|
if (mp->m_dir_inode_ops)
|
|
return mp->m_dir_inode_ops;
|
|
if (xfs_sb_version_hascrc(&mp->m_sb))
|
|
return &xfs_dir3_ops;
|
|
if (xfs_sb_version_hasftype(&mp->m_sb))
|
|
return &xfs_dir2_ftype_ops;
|
|
return &xfs_dir2_ops;
|
|
}
|