* [PATCH 01/32] xfsprogs: fix automatic dependency generation
[not found] <1380510944-8571-1-git-send-email-david@fromorbit.com>
@ 2013-09-30 3:15 ` Dave Chinner
2013-10-08 23:00 ` Eric Sandeen
2013-09-30 3:15 ` [PATCH 02/32] libxfs: fix missing filetype updates to xfs_dir2.c Dave Chinner
` (30 subsequent siblings)
31 siblings, 1 reply; 56+ messages in thread
From: Dave Chinner @ 2013-09-30 3:15 UTC (permalink / raw)
To: xfs
From: Dave Chinner <dchinner@redhat.com>
Adding are removing a header file does not result in dependency
regeneration like it should. make clean will rebuild the
dependencies, but a normal make won't. Fix it.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
include/buildrules | 20 ++++++++++++++++----
1 file changed, 16 insertions(+), 4 deletions(-)
diff --git a/include/buildrules b/include/buildrules
index 49cb2a4..edb1beb 100644
--- a/include/buildrules
+++ b/include/buildrules
@@ -79,18 +79,30 @@ endif # _BUILDRULES_INCLUDED_
$(_FORCE):
# dependency build is automatic, relies on gcc -MM to generate.
+#
+# This is a bit messy. It regenerates the depenencies on each build so
+# that we catch files being added and removed. There are other ways of doing
+# this (e.g. per-file dependency files) but that requires more in-depth changes
+# to the build system. Compile time is not an issue for us, so the
+# rebuild on every make invocation isn't a problem we need to care about. Just
+# do it silently so it doesn't make the build unnecessarily noisy.
+
.PHONY : depend ltdepend install-qa
MAKEDEP := $(MAKEDEPEND) $(CFLAGS)
-ltdepend: .ltdep
+ltdepend: rmltdep .ltdep
+
+rmltdep:
+ @rm -f .ltdep
.ltdep: $(CFILES) $(HFILES)
- @echo " [LTDEP]"
$(Q)$(MAKEDEP) $(CFILES) | $(SED) -e 's,^\([^:]*\)\.o,\1.lo,' > .ltdep
-depend: .dep
+depend: rmdep .dep
+
+rmdep:
+ @rm -f .dep
.dep: $(CFILES) $(HFILES)
- @echo " [DEP]"
$(Q)$(MAKEDEP) $(CFILES) > .dep
--
1.8.3.2
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 02/32] libxfs: fix missing filetype updates to xfs_dir2.c
[not found] <1380510944-8571-1-git-send-email-david@fromorbit.com>
2013-09-30 3:15 ` [PATCH 01/32] xfsprogs: fix automatic dependency generation Dave Chinner
@ 2013-09-30 3:15 ` Dave Chinner
2013-10-08 22:53 ` Eric Sandeen
2013-10-18 16:45 ` Rich Johnston
2013-09-30 3:15 ` [PATCH 03/32] xfs: fix some minor sparse warnings Dave Chinner
` (29 subsequent siblings)
31 siblings, 2 replies; 56+ messages in thread
From: Dave Chinner @ 2013-09-30 3:15 UTC (permalink / raw)
To: xfs
From: Dave Chinner <dchinner@redhat.com>
They were missed in the original patch that was committed.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
libxfs/xfs_dir2.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/libxfs/xfs_dir2.c b/libxfs/xfs_dir2.c
index 010c701..96a3c1d 100644
--- a/libxfs/xfs_dir2.c
+++ b/libxfs/xfs_dir2.c
@@ -194,6 +194,7 @@ xfs_dir_createname(
memset(&args, 0, sizeof(xfs_da_args_t));
args.name = name->name;
args.namelen = name->len;
+ args.filetype = name->type;
args.hashval = dp->i_mount->m_dirnameops->hashname(name);
args.inumber = inum;
args.dp = dp;
@@ -268,6 +269,7 @@ xfs_dir_lookup(
memset(&args, 0, sizeof(xfs_da_args_t));
args.name = name->name;
args.namelen = name->len;
+ args.filetype = name->type;
args.hashval = dp->i_mount->m_dirnameops->hashname(name);
args.dp = dp;
args.whichfork = XFS_DATA_FORK;
@@ -323,6 +325,7 @@ xfs_dir_removename(
memset(&args, 0, sizeof(xfs_da_args_t));
args.name = name->name;
args.namelen = name->len;
+ args.filetype = name->type;
args.hashval = dp->i_mount->m_dirnameops->hashname(name);
args.inumber = ino;
args.dp = dp;
--
1.8.3.2
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 03/32] xfs: fix some minor sparse warnings
[not found] <1380510944-8571-1-git-send-email-david@fromorbit.com>
2013-09-30 3:15 ` [PATCH 01/32] xfsprogs: fix automatic dependency generation Dave Chinner
2013-09-30 3:15 ` [PATCH 02/32] libxfs: fix missing filetype updates to xfs_dir2.c Dave Chinner
@ 2013-09-30 3:15 ` Dave Chinner
2013-10-08 22:56 ` Eric Sandeen
2013-09-30 3:15 ` [PATCH 04/32] xfs: check magic numbers in dir3 leaf verifier first Dave Chinner
` (28 subsequent siblings)
31 siblings, 1 reply; 56+ messages in thread
From: Dave Chinner @ 2013-09-30 3:15 UTC (permalink / raw)
To: xfs
From: Dave Chinner <dchinner@redhat.com>
A couple of simple locking annotations and 0 vs NULL warnings.
Nothing that changes any code behaviour, just removes build noise.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
libxfs/xfs_bmap.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c
index 2d480cc..7336abf 100644
--- a/libxfs/xfs_bmap.c
+++ b/libxfs/xfs_bmap.c
@@ -4415,7 +4415,7 @@ xfs_bmapi_write(
{
struct xfs_mount *mp = ip->i_mount;
struct xfs_ifork *ifp;
- struct xfs_bmalloca bma = { 0 }; /* args for xfs_bmap_alloc */
+ struct xfs_bmalloca bma = { NULL }; /* args for xfs_bmap_alloc */
xfs_fileoff_t end; /* end of mapped file region */
int eof; /* after the end of extents */
int error; /* error return */
--
1.8.3.2
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 04/32] xfs: check magic numbers in dir3 leaf verifier first
[not found] <1380510944-8571-1-git-send-email-david@fromorbit.com>
` (2 preceding siblings ...)
2013-09-30 3:15 ` [PATCH 03/32] xfs: fix some minor sparse warnings Dave Chinner
@ 2013-09-30 3:15 ` Dave Chinner
2013-10-08 23:03 ` Eric Sandeen
2013-09-30 3:15 ` [PATCH 05/32] xfs: ensure we copy buffer type in da btree root splits Dave Chinner
` (27 subsequent siblings)
31 siblings, 1 reply; 56+ messages in thread
From: Dave Chinner @ 2013-09-30 3:15 UTC (permalink / raw)
To: xfs
From: Dave Chinner <dchinner@redhat.com>
Calling xfs_dir3_leaf_hdr_from_disk() in a verifier before
validating the magic numbers in the buffer results in ASSERT
failures due to mismatching magic numbers when a corruption occurs.
Seeing as the verifier is supposed to catch the corruption and pass
it back to the caller, having the verifier assert fail on error
defeats the purpose of detecting the errors in the first place.
Check the magic numbers direct from the buffer before decoding the
header.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
libxfs/xfs_dir2_leaf.c | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/libxfs/xfs_dir2_leaf.c b/libxfs/xfs_dir2_leaf.c
index 7ec2f19..c035c4d 100644
--- a/libxfs/xfs_dir2_leaf.c
+++ b/libxfs/xfs_dir2_leaf.c
@@ -161,6 +161,11 @@ xfs_dir3_leaf_check_int(
return true;
}
+/*
+ * We verify the magic numbers before decoding the leaf header so that on debug
+ * kernels we don't get assertion failures in xfs_dir3_leaf_hdr_from_disk() due
+ * to incorrect magic numbers.
+ */
static bool
xfs_dir3_leaf_verify(
struct xfs_buf *bp,
@@ -172,24 +177,25 @@ xfs_dir3_leaf_verify(
ASSERT(magic == XFS_DIR2_LEAF1_MAGIC || magic == XFS_DIR2_LEAFN_MAGIC);
- xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf);
if (xfs_sb_version_hascrc(&mp->m_sb)) {
struct xfs_dir3_leaf_hdr *leaf3 = bp->b_addr;
+ __uint16_t magic3;
- if ((magic == XFS_DIR2_LEAF1_MAGIC &&
- leafhdr.magic != XFS_DIR3_LEAF1_MAGIC) ||
- (magic == XFS_DIR2_LEAFN_MAGIC &&
- leafhdr.magic != XFS_DIR3_LEAFN_MAGIC))
- return false;
+ magic3 = (magic == XFS_DIR2_LEAF1_MAGIC) ? XFS_DIR3_LEAF1_MAGIC
+ : XFS_DIR3_LEAFN_MAGIC;
+ if (leaf3->info.hdr.magic != cpu_to_be16(magic3))
+ return false;
if (!uuid_equal(&leaf3->info.uuid, &mp->m_sb.sb_uuid))
return false;
if (be64_to_cpu(leaf3->info.blkno) != bp->b_bn)
return false;
} else {
- if (leafhdr.magic != magic)
+ if (leaf->hdr.info.magic != cpu_to_be16(magic))
return false;
}
+
+ xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf);
return xfs_dir3_leaf_check_int(mp, &leafhdr, leaf);
}
--
1.8.3.2
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 05/32] xfs: ensure we copy buffer type in da btree root splits
[not found] <1380510944-8571-1-git-send-email-david@fromorbit.com>
` (3 preceding siblings ...)
2013-09-30 3:15 ` [PATCH 04/32] xfs: check magic numbers in dir3 leaf verifier first Dave Chinner
@ 2013-09-30 3:15 ` Dave Chinner
2013-10-08 23:06 ` Eric Sandeen
2013-10-18 16:49 ` Rich Johnston
2013-09-30 3:15 ` [PATCH 06/32] xfs: don't assert fail on bad inode numbers Dave Chinner
` (26 subsequent siblings)
31 siblings, 2 replies; 56+ messages in thread
From: Dave Chinner @ 2013-09-30 3:15 UTC (permalink / raw)
To: xfs
From: Dave Chinner <dchinner@redhat.com>
When splitting the root of the da btree, we shuffled data between
buffers and the structures that track them. At one point, we copy
data and state from one buffer to another, including the ops
associated with the buffer. When we do this, we also need to copy
the buffer type associated with the buf log item so that the buffer
is logged correctly. If we don't do that, log recovery won't
recognise it and hence it won't recalculate the CRC on the buffer
after recovery. This leads to a directory block that can't be read
after recovery has run.
Found by inspection after finding the same problem with remote
symlink buffers.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
libxfs/xfs_da_btree.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/libxfs/xfs_da_btree.c b/libxfs/xfs_da_btree.c
index b7b6705..f106e06 100644
--- a/libxfs/xfs_da_btree.c
+++ b/libxfs/xfs_da_btree.c
@@ -612,6 +612,7 @@ xfs_da3_root_split(
xfs_trans_log_buf(tp, bp, 0, size - 1);
bp->b_ops = blk1->bp->b_ops;
+ xfs_trans_buf_copy_type(bp, blk1->bp);
blk1->bp = bp;
blk1->blkno = blkno;
--
1.8.3.2
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 06/32] xfs: don't assert fail on bad inode numbers
[not found] <1380510944-8571-1-git-send-email-david@fromorbit.com>
` (4 preceding siblings ...)
2013-09-30 3:15 ` [PATCH 05/32] xfs: ensure we copy buffer type in da btree root splits Dave Chinner
@ 2013-09-30 3:15 ` Dave Chinner
2013-10-08 23:09 ` Eric Sandeen
2013-09-30 3:15 ` [PATCH 07/32] xfs: dirent dtype presence is dependent on directory magic numbers Dave Chinner
` (25 subsequent siblings)
31 siblings, 1 reply; 56+ messages in thread
From: Dave Chinner @ 2013-09-30 3:15 UTC (permalink / raw)
To: xfs
From: Dave Chinner <dchinner@redhat.com>
Let the inode verifier do it's work by returning an error when we
fail to find correct magic numbers in an inode buffer.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
libxfs/xfs_inode_buf.c | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/libxfs/xfs_inode_buf.c b/libxfs/xfs_inode_buf.c
index 6205318..b096f77 100644
--- a/libxfs/xfs_inode_buf.c
+++ b/libxfs/xfs_inode_buf.c
@@ -39,9 +39,8 @@ xfs_inobp_check(
i * mp->m_sb.sb_inodesize);
if (!dip->di_next_unlinked) {
xfs_alert(mp,
- "Detected bogus zero next_unlinked field in incore inode buffer 0x%p.",
- bp);
- ASSERT(dip->di_next_unlinked);
+ "Detected bogus zero next_unlinked field in inode %d buffer 0x%llx.",
+ i, (long long)bp->b_bn);
}
}
}
@@ -74,11 +73,10 @@ xfs_inode_buf_verify(
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_HIGH,
mp, dip);
#ifdef DEBUG
- xfs_emerg(mp,
+ xfs_alert(mp,
"bad inode magic/vsn daddr %lld #%d (magic=%x)",
(unsigned long long)bp->b_bn, i,
be16_to_cpu(dip->di_magic));
- ASSERT(0);
#endif
}
}
--
1.8.3.2
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 07/32] xfs: dirent dtype presence is dependent on directory magic numbers
[not found] <1380510944-8571-1-git-send-email-david@fromorbit.com>
` (5 preceding siblings ...)
2013-09-30 3:15 ` [PATCH 06/32] xfs: don't assert fail on bad inode numbers Dave Chinner
@ 2013-09-30 3:15 ` Dave Chinner
2013-10-08 23:30 ` Eric Sandeen
2013-09-30 3:15 ` [PATCH 08/32] xfs: create a shared header file for format-related information Dave Chinner
` (24 subsequent siblings)
31 siblings, 1 reply; 56+ messages in thread
From: Dave Chinner @ 2013-09-30 3:15 UTC (permalink / raw)
To: xfs
From: Dave Chinner <dchinner@redhat.com>
The determination of whether a directory entry contains a dtype
field originally was dependent on the filesystem having CRCs
enabled. This meant that the format for dtype beign enabled could be
determined by checking the directory block magic number rather than
doing a feature bit check. This was useful in that it meant that we
didn't need to pass a struct xfs_mount around to functions that
were already supplied with a directory block header.
Unfortunately, the introduction of dtype fields into the v4
structure via a feature bit meant this "use the directory block
magic number" method of discriminating the dirent entry sizes is
broken. Hence we need to convert the places that use magic number
checks to use feature bit checks so that they work correctly and not
by chance.
The current code works on v4 filesystems only because the dirent
size roundup covers the extra byte needed by the dtype field in the
places where this problem occurs.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
db/check.c | 2 +-
include/xfs_dir2_format.h | 51 +++++++++++++++++++----------------------------
libxfs/xfs_dir2_block.c | 6 +++---
libxfs/xfs_dir2_sf.c | 6 +++---
repair/dir2.c | 4 ++--
5 files changed, 29 insertions(+), 40 deletions(-)
diff --git a/db/check.c b/db/check.c
index 2d4718d..4867698 100644
--- a/db/check.c
+++ b/db/check.c
@@ -3434,7 +3434,7 @@ process_sf_dir_v2(
dbprintf(_("dir %lld entry . %lld\n"), id->ino, id->ino);
(*dot)++;
sfe = xfs_dir2_sf_firstentry(sf);
- offset = XFS_DIR3_DATA_FIRST_OFFSET(mp);
+ offset = xfs_dir3_data_first_offset(mp);
for (i = sf->count - 1, i8 = 0; i >= 0; i--) {
if ((__psint_t)sfe + xfs_dir3_sf_entsize(mp, sf, sfe->namelen) -
(__psint_t)sf > be64_to_cpu(dip->di_size)) {
diff --git a/include/xfs_dir2_format.h b/include/xfs_dir2_format.h
index a0961a6..9cf6738 100644
--- a/include/xfs_dir2_format.h
+++ b/include/xfs_dir2_format.h
@@ -497,69 +497,58 @@ xfs_dir3_data_unused_p(struct xfs_dir2_data_hdr *hdr)
/*
* Offsets of . and .. in data space (always block 0)
*
- * The macros are used for shortform directories as they have no headers to read
- * the magic number out of. Shortform directories need to know the size of the
- * data block header because the sfe embeds the block offset of the entry into
- * it so that it doesn't change when format conversion occurs. Bad Things Happen
- * if we don't follow this rule.
- *
* XXX: there is scope for significant optimisation of the logic here. Right
* now we are checking for "dir3 format" over and over again. Ideally we should
* only do it once for each operation.
*/
-#define XFS_DIR3_DATA_DOT_OFFSET(mp) \
- xfs_dir3_data_hdr_size(xfs_sb_version_hascrc(&(mp)->m_sb))
-#define XFS_DIR3_DATA_DOTDOT_OFFSET(mp) \
- (XFS_DIR3_DATA_DOT_OFFSET(mp) + xfs_dir3_data_entsize(mp, 1))
-#define XFS_DIR3_DATA_FIRST_OFFSET(mp) \
- (XFS_DIR3_DATA_DOTDOT_OFFSET(mp) + xfs_dir3_data_entsize(mp, 2))
-
static inline xfs_dir2_data_aoff_t
-xfs_dir3_data_dot_offset(struct xfs_dir2_data_hdr *hdr)
+xfs_dir3_data_dot_offset(struct xfs_mount *mp)
{
- return xfs_dir3_data_entry_offset(hdr);
+ return xfs_dir3_data_hdr_size(xfs_sb_version_hascrc(&mp->m_sb));
}
static inline xfs_dir2_data_aoff_t
-xfs_dir3_data_dotdot_offset(struct xfs_dir2_data_hdr *hdr)
+xfs_dir3_data_dotdot_offset(struct xfs_mount *mp)
{
- bool dir3 = hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
- hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC);
- return xfs_dir3_data_dot_offset(hdr) +
- __xfs_dir3_data_entsize(dir3, 1);
+ return xfs_dir3_data_dot_offset(mp) +
+ xfs_dir3_data_entsize(mp, 1);
}
static inline xfs_dir2_data_aoff_t
-xfs_dir3_data_first_offset(struct xfs_dir2_data_hdr *hdr)
+xfs_dir3_data_first_offset(struct xfs_mount *mp)
{
- bool dir3 = hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
- hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC);
- return xfs_dir3_data_dotdot_offset(hdr) +
- __xfs_dir3_data_entsize(dir3, 2);
+ return xfs_dir3_data_dotdot_offset(mp) +
+ xfs_dir3_data_entsize(mp, 2);
}
/*
* location of . and .. in data space (always block 0)
*/
static inline struct xfs_dir2_data_entry *
-xfs_dir3_data_dot_entry_p(struct xfs_dir2_data_hdr *hdr)
+xfs_dir3_data_dot_entry_p(
+ struct xfs_mount *mp,
+ struct xfs_dir2_data_hdr *hdr)
{
return (struct xfs_dir2_data_entry *)
- ((char *)hdr + xfs_dir3_data_dot_offset(hdr));
+ ((char *)hdr + xfs_dir3_data_dot_offset(mp));
}
static inline struct xfs_dir2_data_entry *
-xfs_dir3_data_dotdot_entry_p(struct xfs_dir2_data_hdr *hdr)
+xfs_dir3_data_dotdot_entry_p(
+ struct xfs_mount *mp,
+ struct xfs_dir2_data_hdr *hdr)
{
return (struct xfs_dir2_data_entry *)
- ((char *)hdr + xfs_dir3_data_dotdot_offset(hdr));
+ ((char *)hdr + xfs_dir3_data_dotdot_offset(mp));
}
static inline struct xfs_dir2_data_entry *
-xfs_dir3_data_first_entry_p(struct xfs_dir2_data_hdr *hdr)
+xfs_dir3_data_first_entry_p(
+ struct xfs_mount *mp,
+ struct xfs_dir2_data_hdr *hdr)
{
return (struct xfs_dir2_data_entry *)
- ((char *)hdr + xfs_dir3_data_first_offset(hdr));
+ ((char *)hdr + xfs_dir3_data_first_offset(mp));
}
/*
diff --git a/libxfs/xfs_dir2_block.c b/libxfs/xfs_dir2_block.c
index 3e4bc53..1d8f598 100644
--- a/libxfs/xfs_dir2_block.c
+++ b/libxfs/xfs_dir2_block.c
@@ -1139,7 +1139,7 @@ xfs_dir2_sf_to_block(
/*
* Create entry for .
*/
- dep = xfs_dir3_data_dot_entry_p(hdr);
+ dep = xfs_dir3_data_dot_entry_p(mp, hdr);
dep->inumber = cpu_to_be64(dp->i_ino);
dep->namelen = 1;
dep->name[0] = '.';
@@ -1153,7 +1153,7 @@ xfs_dir2_sf_to_block(
/*
* Create entry for ..
*/
- dep = xfs_dir3_data_dotdot_entry_p(hdr);
+ dep = xfs_dir3_data_dotdot_entry_p(mp, hdr);
dep->inumber = cpu_to_be64(xfs_dir2_sf_get_parent_ino(sfp));
dep->namelen = 2;
dep->name[0] = dep->name[1] = '.';
@@ -1164,7 +1164,7 @@ xfs_dir2_sf_to_block(
blp[1].hashval = cpu_to_be32(xfs_dir_hash_dotdot);
blp[1].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp,
(char *)dep - (char *)hdr));
- offset = xfs_dir3_data_first_offset(hdr);
+ offset = xfs_dir3_data_first_offset(mp);
/*
* Loop over existing entries, stuff them in.
*/
diff --git a/libxfs/xfs_dir2_sf.c b/libxfs/xfs_dir2_sf.c
index 740cab0..7580333 100644
--- a/libxfs/xfs_dir2_sf.c
+++ b/libxfs/xfs_dir2_sf.c
@@ -540,7 +540,7 @@ xfs_dir2_sf_addname_hard(
* to insert the new entry.
* If it's going to end up at the end then oldsfep will point there.
*/
- for (offset = XFS_DIR3_DATA_FIRST_OFFSET(mp),
+ for (offset = xfs_dir3_data_first_offset(mp),
oldsfep = xfs_dir2_sf_firstentry(oldsfp),
add_datasize = xfs_dir3_data_entsize(mp, args->namelen),
eof = (char *)oldsfep == &buf[old_isize];
@@ -623,7 +623,7 @@ xfs_dir2_sf_addname_pick(
sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
size = xfs_dir3_data_entsize(mp, args->namelen);
- offset = XFS_DIR3_DATA_FIRST_OFFSET(mp);
+ offset = xfs_dir3_data_first_offset(mp);
sfep = xfs_dir2_sf_firstentry(sfp);
holefit = 0;
/*
@@ -696,7 +696,7 @@ xfs_dir2_sf_check(
mp = dp->i_mount;
sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
- offset = XFS_DIR3_DATA_FIRST_OFFSET(mp);
+ offset = xfs_dir3_data_first_offset(mp);
ino = xfs_dir2_sf_get_parent_ino(sfp);
i8count = ino > XFS_DIR2_MAX_SHORT_INUM;
diff --git a/repair/dir2.c b/repair/dir2.c
index a856631..d931d1d 100644
--- a/repair/dir2.c
+++ b/repair/dir2.c
@@ -705,7 +705,7 @@ process_sf_dir2_fixoff(
sfp = (struct xfs_dir2_sf_hdr *)XFS_DFORK_DPTR(dip);
sfep = xfs_dir2_sf_firstentry(sfp);
- offset = XFS_DIR3_DATA_FIRST_OFFSET(mp);
+ offset = xfs_dir3_data_first_offset(mp);
for (i = 0; i < sfp->count; i++) {
xfs_dir2_sf_put_offset(sfep, offset);
@@ -759,7 +759,7 @@ process_sf_dir2(
max_size = XFS_DFORK_DSIZE(dip, mp);
num_entries = sfp->count;
ino_dir_size = be64_to_cpu(dip->di_size);
- offset = XFS_DIR3_DATA_FIRST_OFFSET(mp);
+ offset = xfs_dir3_data_first_offset(mp);
bad_offset = *repair = 0;
ASSERT(ino_dir_size <= max_size);
--
1.8.3.2
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 08/32] xfs: create a shared header file for format-related information
[not found] <1380510944-8571-1-git-send-email-david@fromorbit.com>
` (6 preceding siblings ...)
2013-09-30 3:15 ` [PATCH 07/32] xfs: dirent dtype presence is dependent on directory magic numbers Dave Chinner
@ 2013-09-30 3:15 ` Dave Chinner
2013-10-08 23:37 ` Eric Sandeen
2013-10-18 16:59 ` Rich Johnston
2013-09-30 3:15 ` [PATCH 09/32] xfs: unify directory/attribute format definitions Dave Chinner
` (23 subsequent siblings)
31 siblings, 2 replies; 56+ messages in thread
From: Dave Chinner @ 2013-09-30 3:15 UTC (permalink / raw)
To: xfs
All of the buffer operations structures are needed to be exported
for xfs_db, so move them all to a common location rather than
spreading them all over the place. They are verifying the on-disk
format, so while xfs_format.h might be a good place, it is not part
of the on disk format.
Hence we need to create a new header file that we centralise these
related definitions. Start by moving the bffer operations
structures, and then also move all the other definitions that have
crept into xfs_log_format.h and xfs_format.h as there was no other
shared header file to put them in.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
include/Makefile | 1 +
include/libxfs.h | 1 +
include/xfs_ag.h | 4 -
include/xfs_alloc.h | 3 -
include/xfs_alloc_btree.h | 2 -
include/xfs_attr_leaf.h | 2 -
include/xfs_attr_remote.h | 2 -
include/xfs_bmap_btree.h | 2 -
include/xfs_da_btree.h | 2 -
include/xfs_format.h | 10 --
include/xfs_ialloc.h | 2 -
include/xfs_ialloc_btree.h | 2 -
include/xfs_inode_buf.h | 2 -
include/xfs_log_format.h | 177 --------------------------------
include/xfs_sb.h | 3 -
include/xfs_shared.h | 244 +++++++++++++++++++++++++++++++++++++++++++++
16 files changed, 246 insertions(+), 213 deletions(-)
create mode 100644 include/xfs_shared.h
diff --git a/include/Makefile b/include/Makefile
index 628a087..fd2d61b 100644
--- a/include/Makefile
+++ b/include/Makefile
@@ -38,6 +38,7 @@ QAHFILES = libxfs.h libxlog.h \
xfs_metadump.h \
xfs_quota_defs.h \
xfs_sb.h \
+ xfs_shared.h \
xfs_trace.h \
xfs_trans_resv.h \
xfs_trans_space.h
diff --git a/include/libxfs.h b/include/libxfs.h
index ffd83bf..a5d6388 100644
--- a/include/libxfs.h
+++ b/include/libxfs.h
@@ -37,6 +37,7 @@
#include <xfs/xfs_fs.h>
#include <xfs/xfs_arch.h>
+#include <xfs/xfs_shared.h>
#include <xfs/xfs_format.h>
#include <xfs/xfs_log_format.h>
#include <xfs/xfs_quota_defs.h>
diff --git a/include/xfs_ag.h b/include/xfs_ag.h
index 1cb740a..3fc1098 100644
--- a/include/xfs_ag.h
+++ b/include/xfs_ag.h
@@ -128,8 +128,6 @@ typedef struct xfs_agf {
extern int xfs_read_agf(struct xfs_mount *mp, struct xfs_trans *tp,
xfs_agnumber_t agno, int flags, struct xfs_buf **bpp);
-extern const struct xfs_buf_ops xfs_agf_buf_ops;
-
/*
* Size of the unlinked inode hash table in the agi.
*/
@@ -191,8 +189,6 @@ typedef struct xfs_agi {
extern int xfs_read_agi(struct xfs_mount *mp, struct xfs_trans *tp,
xfs_agnumber_t agno, struct xfs_buf **bpp);
-extern const struct xfs_buf_ops xfs_agi_buf_ops;
-
/*
* The third a.g. block contains the a.g. freelist, an array
* of block pointers to blocks owned by the allocation btree code.
diff --git a/include/xfs_alloc.h b/include/xfs_alloc.h
index 99d0a61..feacb06 100644
--- a/include/xfs_alloc.h
+++ b/include/xfs_alloc.h
@@ -231,7 +231,4 @@ xfs_alloc_get_rec(
xfs_extlen_t *len, /* output: length of extent */
int *stat); /* output: success/failure */
-extern const struct xfs_buf_ops xfs_agf_buf_ops;
-extern const struct xfs_buf_ops xfs_agfl_buf_ops;
-
#endif /* __XFS_ALLOC_H__ */
diff --git a/include/xfs_alloc_btree.h b/include/xfs_alloc_btree.h
index e3a3f74..72676c3 100644
--- a/include/xfs_alloc_btree.h
+++ b/include/xfs_alloc_btree.h
@@ -95,6 +95,4 @@ extern struct xfs_btree_cur *xfs_allocbt_init_cursor(struct xfs_mount *,
xfs_agnumber_t, xfs_btnum_t);
extern int xfs_allocbt_maxrecs(struct xfs_mount *, int, int);
-extern const struct xfs_buf_ops xfs_allocbt_buf_ops;
-
#endif /* __XFS_ALLOC_BTREE_H__ */
diff --git a/include/xfs_attr_leaf.h b/include/xfs_attr_leaf.h
index c102213..da34e64 100644
--- a/include/xfs_attr_leaf.h
+++ b/include/xfs_attr_leaf.h
@@ -336,6 +336,4 @@ void xfs_attr3_leaf_hdr_from_disk(struct xfs_attr3_icleaf_hdr *to,
void xfs_attr3_leaf_hdr_to_disk(struct xfs_attr_leafblock *to,
struct xfs_attr3_icleaf_hdr *from);
-extern const struct xfs_buf_ops xfs_attr3_leaf_buf_ops;
-
#endif /* __XFS_ATTR_LEAF_H__ */
diff --git a/include/xfs_attr_remote.h b/include/xfs_attr_remote.h
index 92a8fd7..b3e1e1b 100644
--- a/include/xfs_attr_remote.h
+++ b/include/xfs_attr_remote.h
@@ -45,8 +45,6 @@ struct xfs_attr3_rmt_hdr {
((bufsize) - (xfs_sb_version_hascrc(&(mp)->m_sb) ? \
sizeof(struct xfs_attr3_rmt_hdr) : 0))
-extern const struct xfs_buf_ops xfs_attr3_rmt_buf_ops;
-
int xfs_attr3_rmt_blocks(struct xfs_mount *mp, int attrlen);
int xfs_attr_rmtval_get(struct xfs_da_args *args);
diff --git a/include/xfs_bmap_btree.h b/include/xfs_bmap_btree.h
index 1b726d6..e307978 100644
--- a/include/xfs_bmap_btree.h
+++ b/include/xfs_bmap_btree.h
@@ -239,6 +239,4 @@ extern int xfs_bmbt_maxrecs(struct xfs_mount *, int blocklen, int leaf);
extern struct xfs_btree_cur *xfs_bmbt_init_cursor(struct xfs_mount *,
struct xfs_trans *, struct xfs_inode *, int);
-extern const struct xfs_buf_ops xfs_bmbt_buf_ops;
-
#endif /* __XFS_BMAP_BTREE_H__ */
diff --git a/include/xfs_da_btree.h b/include/xfs_da_btree.h
index b1f2679..a762cfa 100644
--- a/include/xfs_da_btree.h
+++ b/include/xfs_da_btree.h
@@ -309,8 +309,6 @@ int xfs_da3_node_read(struct xfs_trans *tp, struct xfs_inode *dp,
xfs_dablk_t bno, xfs_daddr_t mappedbno,
struct xfs_buf **bpp, int which_fork);
-extern const struct xfs_buf_ops xfs_da3_node_buf_ops;
-
/*
* Utility routines.
*/
diff --git a/include/xfs_format.h b/include/xfs_format.h
index 35c08ff..a790428 100644
--- a/include/xfs_format.h
+++ b/include/xfs_format.h
@@ -156,14 +156,4 @@ struct xfs_dsymlink_hdr {
((bufsize) - (xfs_sb_version_hascrc(&(mp)->m_sb) ? \
sizeof(struct xfs_dsymlink_hdr) : 0))
-int xfs_symlink_blocks(struct xfs_mount *mp, int pathlen);
-int xfs_symlink_hdr_set(struct xfs_mount *mp, xfs_ino_t ino, uint32_t offset,
- uint32_t size, struct xfs_buf *bp);
-bool xfs_symlink_hdr_ok(struct xfs_mount *mp, xfs_ino_t ino, uint32_t offset,
- uint32_t size, struct xfs_buf *bp);
-void xfs_symlink_local_to_remote(struct xfs_trans *tp, struct xfs_buf *bp,
- struct xfs_inode *ip, struct xfs_ifork *ifp);
-
-extern const struct xfs_buf_ops xfs_symlink_buf_ops;
-
#endif /* __XFS_FORMAT_H__ */
diff --git a/include/xfs_ialloc.h b/include/xfs_ialloc.h
index 68c0732..1557798 100644
--- a/include/xfs_ialloc.h
+++ b/include/xfs_ialloc.h
@@ -158,6 +158,4 @@ int xfs_ialloc_inode_init(struct xfs_mount *mp, struct xfs_trans *tp,
xfs_agnumber_t agno, xfs_agblock_t agbno,
xfs_agblock_t length, unsigned int gen);
-extern const struct xfs_buf_ops xfs_agi_buf_ops;
-
#endif /* __XFS_IALLOC_H__ */
diff --git a/include/xfs_ialloc_btree.h b/include/xfs_ialloc_btree.h
index 3ac36b7..cfbfe46 100644
--- a/include/xfs_ialloc_btree.h
+++ b/include/xfs_ialloc_btree.h
@@ -110,6 +110,4 @@ extern struct xfs_btree_cur *xfs_inobt_init_cursor(struct xfs_mount *,
struct xfs_trans *, struct xfs_buf *, xfs_agnumber_t);
extern int xfs_inobt_maxrecs(struct xfs_mount *, int, int);
-extern const struct xfs_buf_ops xfs_inobt_buf_ops;
-
#endif /* __XFS_IALLOC_BTREE_H__ */
diff --git a/include/xfs_inode_buf.h b/include/xfs_inode_buf.h
index aae9fc4..e8fd3bd 100644
--- a/include/xfs_inode_buf.h
+++ b/include/xfs_inode_buf.h
@@ -47,6 +47,4 @@ void xfs_inobp_check(struct xfs_mount *, struct xfs_buf *);
#define xfs_inobp_check(mp, bp)
#endif /* DEBUG */
-extern const struct xfs_buf_ops xfs_inode_buf_ops;
-
#endif /* __XFS_INODE_BUF_H__ */
diff --git a/include/xfs_log_format.h b/include/xfs_log_format.h
index 31e3a06..aeaa715 100644
--- a/include/xfs_log_format.h
+++ b/include/xfs_log_format.h
@@ -234,178 +234,6 @@ typedef struct xfs_trans_header {
{ XFS_LI_ICREATE, "XFS_LI_ICREATE" }
/*
- * Transaction types. Used to distinguish types of buffers.
- */
-#define XFS_TRANS_SETATTR_NOT_SIZE 1
-#define XFS_TRANS_SETATTR_SIZE 2
-#define XFS_TRANS_INACTIVE 3
-#define XFS_TRANS_CREATE 4
-#define XFS_TRANS_CREATE_TRUNC 5
-#define XFS_TRANS_TRUNCATE_FILE 6
-#define XFS_TRANS_REMOVE 7
-#define XFS_TRANS_LINK 8
-#define XFS_TRANS_RENAME 9
-#define XFS_TRANS_MKDIR 10
-#define XFS_TRANS_RMDIR 11
-#define XFS_TRANS_SYMLINK 12
-#define XFS_TRANS_SET_DMATTRS 13
-#define XFS_TRANS_GROWFS 14
-#define XFS_TRANS_STRAT_WRITE 15
-#define XFS_TRANS_DIOSTRAT 16
-/* 17 was XFS_TRANS_WRITE_SYNC */
-#define XFS_TRANS_WRITEID 18
-#define XFS_TRANS_ADDAFORK 19
-#define XFS_TRANS_ATTRINVAL 20
-#define XFS_TRANS_ATRUNCATE 21
-#define XFS_TRANS_ATTR_SET 22
-#define XFS_TRANS_ATTR_RM 23
-#define XFS_TRANS_ATTR_FLAG 24
-#define XFS_TRANS_CLEAR_AGI_BUCKET 25
-#define XFS_TRANS_QM_SBCHANGE 26
-/*
- * Dummy entries since we use the transaction type to index into the
- * trans_type[] in xlog_recover_print_trans_head()
- */
-#define XFS_TRANS_DUMMY1 27
-#define XFS_TRANS_DUMMY2 28
-#define XFS_TRANS_QM_QUOTAOFF 29
-#define XFS_TRANS_QM_DQALLOC 30
-#define XFS_TRANS_QM_SETQLIM 31
-#define XFS_TRANS_QM_DQCLUSTER 32
-#define XFS_TRANS_QM_QINOCREATE 33
-#define XFS_TRANS_QM_QUOTAOFF_END 34
-#define XFS_TRANS_SB_UNIT 35
-#define XFS_TRANS_FSYNC_TS 36
-#define XFS_TRANS_GROWFSRT_ALLOC 37
-#define XFS_TRANS_GROWFSRT_ZERO 38
-#define XFS_TRANS_GROWFSRT_FREE 39
-#define XFS_TRANS_SWAPEXT 40
-#define XFS_TRANS_SB_COUNT 41
-#define XFS_TRANS_CHECKPOINT 42
-#define XFS_TRANS_ICREATE 43
-#define XFS_TRANS_TYPE_MAX 43
-/* new transaction types need to be reflected in xfs_logprint(8) */
-
-#define XFS_TRANS_TYPES \
- { XFS_TRANS_SETATTR_NOT_SIZE, "SETATTR_NOT_SIZE" }, \
- { XFS_TRANS_SETATTR_SIZE, "SETATTR_SIZE" }, \
- { XFS_TRANS_INACTIVE, "INACTIVE" }, \
- { XFS_TRANS_CREATE, "CREATE" }, \
- { XFS_TRANS_CREATE_TRUNC, "CREATE_TRUNC" }, \
- { XFS_TRANS_TRUNCATE_FILE, "TRUNCATE_FILE" }, \
- { XFS_TRANS_REMOVE, "REMOVE" }, \
- { XFS_TRANS_LINK, "LINK" }, \
- { XFS_TRANS_RENAME, "RENAME" }, \
- { XFS_TRANS_MKDIR, "MKDIR" }, \
- { XFS_TRANS_RMDIR, "RMDIR" }, \
- { XFS_TRANS_SYMLINK, "SYMLINK" }, \
- { XFS_TRANS_SET_DMATTRS, "SET_DMATTRS" }, \
- { XFS_TRANS_GROWFS, "GROWFS" }, \
- { XFS_TRANS_STRAT_WRITE, "STRAT_WRITE" }, \
- { XFS_TRANS_DIOSTRAT, "DIOSTRAT" }, \
- { XFS_TRANS_WRITEID, "WRITEID" }, \
- { XFS_TRANS_ADDAFORK, "ADDAFORK" }, \
- { XFS_TRANS_ATTRINVAL, "ATTRINVAL" }, \
- { XFS_TRANS_ATRUNCATE, "ATRUNCATE" }, \
- { XFS_TRANS_ATTR_SET, "ATTR_SET" }, \
- { XFS_TRANS_ATTR_RM, "ATTR_RM" }, \
- { XFS_TRANS_ATTR_FLAG, "ATTR_FLAG" }, \
- { XFS_TRANS_CLEAR_AGI_BUCKET, "CLEAR_AGI_BUCKET" }, \
- { XFS_TRANS_QM_SBCHANGE, "QM_SBCHANGE" }, \
- { XFS_TRANS_QM_QUOTAOFF, "QM_QUOTAOFF" }, \
- { XFS_TRANS_QM_DQALLOC, "QM_DQALLOC" }, \
- { XFS_TRANS_QM_SETQLIM, "QM_SETQLIM" }, \
- { XFS_TRANS_QM_DQCLUSTER, "QM_DQCLUSTER" }, \
- { XFS_TRANS_QM_QINOCREATE, "QM_QINOCREATE" }, \
- { XFS_TRANS_QM_QUOTAOFF_END, "QM_QOFF_END" }, \
- { XFS_TRANS_SB_UNIT, "SB_UNIT" }, \
- { XFS_TRANS_FSYNC_TS, "FSYNC_TS" }, \
- { XFS_TRANS_GROWFSRT_ALLOC, "GROWFSRT_ALLOC" }, \
- { XFS_TRANS_GROWFSRT_ZERO, "GROWFSRT_ZERO" }, \
- { XFS_TRANS_GROWFSRT_FREE, "GROWFSRT_FREE" }, \
- { XFS_TRANS_SWAPEXT, "SWAPEXT" }, \
- { XFS_TRANS_SB_COUNT, "SB_COUNT" }, \
- { XFS_TRANS_CHECKPOINT, "CHECKPOINT" }, \
- { XFS_TRANS_DUMMY1, "DUMMY1" }, \
- { XFS_TRANS_DUMMY2, "DUMMY2" }, \
- { XLOG_UNMOUNT_REC_TYPE, "UNMOUNT" }
-
-/*
- * This structure is used to track log items associated with
- * a transaction. It points to the log item and keeps some
- * flags to track the state of the log item. It also tracks
- * the amount of space needed to log the item it describes
- * once we get to commit processing (see xfs_trans_commit()).
- */
-struct xfs_log_item_desc {
- struct xfs_log_item *lid_item;
- struct list_head lid_trans;
- unsigned char lid_flags;
-};
-
-#define XFS_LID_DIRTY 0x1
-
-/*
- * Values for t_flags.
- */
-#define XFS_TRANS_DIRTY 0x01 /* something needs to be logged */
-#define XFS_TRANS_SB_DIRTY 0x02 /* superblock is modified */
-#define XFS_TRANS_PERM_LOG_RES 0x04 /* xact took a permanent log res */
-#define XFS_TRANS_SYNC 0x08 /* make commit synchronous */
-#define XFS_TRANS_DQ_DIRTY 0x10 /* at least one dquot in trx dirty */
-#define XFS_TRANS_RESERVE 0x20 /* OK to use reserved data blocks */
-#define XFS_TRANS_FREEZE_PROT 0x40 /* Transaction has elevated writer
- count in superblock */
-
-/*
- * Values for call flags parameter.
- */
-#define XFS_TRANS_RELEASE_LOG_RES 0x4
-#define XFS_TRANS_ABORT 0x8
-
-/*
- * Field values for xfs_trans_mod_sb.
- */
-#define XFS_TRANS_SB_ICOUNT 0x00000001
-#define XFS_TRANS_SB_IFREE 0x00000002
-#define XFS_TRANS_SB_FDBLOCKS 0x00000004
-#define XFS_TRANS_SB_RES_FDBLOCKS 0x00000008
-#define XFS_TRANS_SB_FREXTENTS 0x00000010
-#define XFS_TRANS_SB_RES_FREXTENTS 0x00000020
-#define XFS_TRANS_SB_DBLOCKS 0x00000040
-#define XFS_TRANS_SB_AGCOUNT 0x00000080
-#define XFS_TRANS_SB_IMAXPCT 0x00000100
-#define XFS_TRANS_SB_REXTSIZE 0x00000200
-#define XFS_TRANS_SB_RBMBLOCKS 0x00000400
-#define XFS_TRANS_SB_RBLOCKS 0x00000800
-#define XFS_TRANS_SB_REXTENTS 0x00001000
-#define XFS_TRANS_SB_REXTSLOG 0x00002000
-
-/*
- * Here we centralize the specification of XFS meta-data buffer
- * reference count values. This determine how hard the buffer
- * cache tries to hold onto the buffer.
- */
-#define XFS_AGF_REF 4
-#define XFS_AGI_REF 4
-#define XFS_AGFL_REF 3
-#define XFS_INO_BTREE_REF 3
-#define XFS_ALLOC_BTREE_REF 2
-#define XFS_BMAP_BTREE_REF 2
-#define XFS_DIR_BTREE_REF 2
-#define XFS_INO_REF 2
-#define XFS_ATTR_BTREE_REF 1
-#define XFS_DQUOT_REF 1
-
-/*
- * Flags for xfs_trans_ichgtime().
- */
-#define XFS_ICHGTIME_MOD 0x1 /* data fork modification timestamp */
-#define XFS_ICHGTIME_CHG 0x2 /* inode field change timestamp */
-#define XFS_ICHGTIME_CREATE 0x4 /* inode create timestamp */
-
-
-/*
* Inode Log Item Format definitions.
*
* This is the structure used to lay out an inode log item in the
@@ -793,7 +621,6 @@ typedef struct xfs_qoff_logformat {
char qf_pad[12]; /* padding for future */
} xfs_qoff_logformat_t;
-
/*
* Disk quotas status in m_qflags, and also sb_qflags. 16 bits.
*/
@@ -845,8 +672,4 @@ struct xfs_icreate_log {
__be32 icl_gen; /* inode generation number to use */
};
-int xfs_log_calc_unit_res(struct xfs_mount *mp, int unit_bytes);
-int xfs_log_calc_minimum_size(struct xfs_mount *);
-
-
#endif /* __XFS_LOG_FORMAT_H__ */
diff --git a/include/xfs_sb.h b/include/xfs_sb.h
index c8d8898..741b7a3 100644
--- a/include/xfs_sb.h
+++ b/include/xfs_sb.h
@@ -695,7 +695,4 @@ extern void xfs_sb_from_disk(struct xfs_sb *, struct xfs_dsb *);
extern void xfs_sb_to_disk(struct xfs_dsb *, struct xfs_sb *, __int64_t);
extern void xfs_sb_quota_from_disk(struct xfs_sb *sbp);
-extern const struct xfs_buf_ops xfs_sb_buf_ops;
-extern const struct xfs_buf_ops xfs_sb_quiet_buf_ops;
-
#endif /* __XFS_SB_H__ */
diff --git a/include/xfs_shared.h b/include/xfs_shared.h
new file mode 100644
index 0000000..63c94b1
--- /dev/null
+++ b/include/xfs_shared.h
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2000-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
+ */
+#ifndef __XFS_SHARED_H__
+#define __XFS_SHARED_H__
+
+/*
+ * Definitions shared between kernel and userspace that don't fit into any other
+ * header file that is shared with userspace.
+ */
+struct xfs_ifork;
+struct xfs_buf;
+struct xfs_buf_ops;
+struct xfs_mount;
+struct xfs_trans;
+struct xfs_inode;
+
+/*
+ * Buffer verifier operations are widely used, including userspace tools
+ */
+extern const struct xfs_buf_ops xfs_agf_buf_ops;
+extern const struct xfs_buf_ops xfs_agi_buf_ops;
+extern const struct xfs_buf_ops xfs_agf_buf_ops;
+extern const struct xfs_buf_ops xfs_agfl_buf_ops;
+extern const struct xfs_buf_ops xfs_allocbt_buf_ops;
+extern const struct xfs_buf_ops xfs_attr3_leaf_buf_ops;
+extern const struct xfs_buf_ops xfs_attr3_rmt_buf_ops;
+extern const struct xfs_buf_ops xfs_bmbt_buf_ops;
+extern const struct xfs_buf_ops xfs_da3_node_buf_ops;
+extern const struct xfs_buf_ops xfs_dquot_buf_ops;
+extern const struct xfs_buf_ops xfs_symlink_buf_ops;
+extern const struct xfs_buf_ops xfs_agi_buf_ops;
+extern const struct xfs_buf_ops xfs_inobt_buf_ops;
+extern const struct xfs_buf_ops xfs_inode_buf_ops;
+extern const struct xfs_buf_ops xfs_inode_buf_ra_ops;
+extern const struct xfs_buf_ops xfs_dquot_buf_ops;
+extern const struct xfs_buf_ops xfs_sb_buf_ops;
+extern const struct xfs_buf_ops xfs_sb_quiet_buf_ops;
+extern const struct xfs_buf_ops xfs_symlink_buf_ops;
+
+/*
+ * Transaction types. Used to distinguish types of buffers. These never reach
+ * the log.
+ */
+#define XFS_TRANS_SETATTR_NOT_SIZE 1
+#define XFS_TRANS_SETATTR_SIZE 2
+#define XFS_TRANS_INACTIVE 3
+#define XFS_TRANS_CREATE 4
+#define XFS_TRANS_CREATE_TRUNC 5
+#define XFS_TRANS_TRUNCATE_FILE 6
+#define XFS_TRANS_REMOVE 7
+#define XFS_TRANS_LINK 8
+#define XFS_TRANS_RENAME 9
+#define XFS_TRANS_MKDIR 10
+#define XFS_TRANS_RMDIR 11
+#define XFS_TRANS_SYMLINK 12
+#define XFS_TRANS_SET_DMATTRS 13
+#define XFS_TRANS_GROWFS 14
+#define XFS_TRANS_STRAT_WRITE 15
+#define XFS_TRANS_DIOSTRAT 16
+/* 17 was XFS_TRANS_WRITE_SYNC */
+#define XFS_TRANS_WRITEID 18
+#define XFS_TRANS_ADDAFORK 19
+#define XFS_TRANS_ATTRINVAL 20
+#define XFS_TRANS_ATRUNCATE 21
+#define XFS_TRANS_ATTR_SET 22
+#define XFS_TRANS_ATTR_RM 23
+#define XFS_TRANS_ATTR_FLAG 24
+#define XFS_TRANS_CLEAR_AGI_BUCKET 25
+#define XFS_TRANS_QM_SBCHANGE 26
+/*
+ * Dummy entries since we use the transaction type to index into the
+ * trans_type[] in xlog_recover_print_trans_head()
+ */
+#define XFS_TRANS_DUMMY1 27
+#define XFS_TRANS_DUMMY2 28
+#define XFS_TRANS_QM_QUOTAOFF 29
+#define XFS_TRANS_QM_DQALLOC 30
+#define XFS_TRANS_QM_SETQLIM 31
+#define XFS_TRANS_QM_DQCLUSTER 32
+#define XFS_TRANS_QM_QINOCREATE 33
+#define XFS_TRANS_QM_QUOTAOFF_END 34
+#define XFS_TRANS_SB_UNIT 35
+#define XFS_TRANS_FSYNC_TS 36
+#define XFS_TRANS_GROWFSRT_ALLOC 37
+#define XFS_TRANS_GROWFSRT_ZERO 38
+#define XFS_TRANS_GROWFSRT_FREE 39
+#define XFS_TRANS_SWAPEXT 40
+#define XFS_TRANS_SB_COUNT 41
+#define XFS_TRANS_CHECKPOINT 42
+#define XFS_TRANS_ICREATE 43
+#define XFS_TRANS_TYPE_MAX 43
+/* new transaction types need to be reflected in xfs_logprint(8) */
+
+#define XFS_TRANS_TYPES \
+ { XFS_TRANS_SETATTR_NOT_SIZE, "SETATTR_NOT_SIZE" }, \
+ { XFS_TRANS_SETATTR_SIZE, "SETATTR_SIZE" }, \
+ { XFS_TRANS_INACTIVE, "INACTIVE" }, \
+ { XFS_TRANS_CREATE, "CREATE" }, \
+ { XFS_TRANS_CREATE_TRUNC, "CREATE_TRUNC" }, \
+ { XFS_TRANS_TRUNCATE_FILE, "TRUNCATE_FILE" }, \
+ { XFS_TRANS_REMOVE, "REMOVE" }, \
+ { XFS_TRANS_LINK, "LINK" }, \
+ { XFS_TRANS_RENAME, "RENAME" }, \
+ { XFS_TRANS_MKDIR, "MKDIR" }, \
+ { XFS_TRANS_RMDIR, "RMDIR" }, \
+ { XFS_TRANS_SYMLINK, "SYMLINK" }, \
+ { XFS_TRANS_SET_DMATTRS, "SET_DMATTRS" }, \
+ { XFS_TRANS_GROWFS, "GROWFS" }, \
+ { XFS_TRANS_STRAT_WRITE, "STRAT_WRITE" }, \
+ { XFS_TRANS_DIOSTRAT, "DIOSTRAT" }, \
+ { XFS_TRANS_WRITEID, "WRITEID" }, \
+ { XFS_TRANS_ADDAFORK, "ADDAFORK" }, \
+ { XFS_TRANS_ATTRINVAL, "ATTRINVAL" }, \
+ { XFS_TRANS_ATRUNCATE, "ATRUNCATE" }, \
+ { XFS_TRANS_ATTR_SET, "ATTR_SET" }, \
+ { XFS_TRANS_ATTR_RM, "ATTR_RM" }, \
+ { XFS_TRANS_ATTR_FLAG, "ATTR_FLAG" }, \
+ { XFS_TRANS_CLEAR_AGI_BUCKET, "CLEAR_AGI_BUCKET" }, \
+ { XFS_TRANS_QM_SBCHANGE, "QM_SBCHANGE" }, \
+ { XFS_TRANS_QM_QUOTAOFF, "QM_QUOTAOFF" }, \
+ { XFS_TRANS_QM_DQALLOC, "QM_DQALLOC" }, \
+ { XFS_TRANS_QM_SETQLIM, "QM_SETQLIM" }, \
+ { XFS_TRANS_QM_DQCLUSTER, "QM_DQCLUSTER" }, \
+ { XFS_TRANS_QM_QINOCREATE, "QM_QINOCREATE" }, \
+ { XFS_TRANS_QM_QUOTAOFF_END, "QM_QOFF_END" }, \
+ { XFS_TRANS_SB_UNIT, "SB_UNIT" }, \
+ { XFS_TRANS_FSYNC_TS, "FSYNC_TS" }, \
+ { XFS_TRANS_GROWFSRT_ALLOC, "GROWFSRT_ALLOC" }, \
+ { XFS_TRANS_GROWFSRT_ZERO, "GROWFSRT_ZERO" }, \
+ { XFS_TRANS_GROWFSRT_FREE, "GROWFSRT_FREE" }, \
+ { XFS_TRANS_SWAPEXT, "SWAPEXT" }, \
+ { XFS_TRANS_SB_COUNT, "SB_COUNT" }, \
+ { XFS_TRANS_CHECKPOINT, "CHECKPOINT" }, \
+ { XFS_TRANS_DUMMY1, "DUMMY1" }, \
+ { XFS_TRANS_DUMMY2, "DUMMY2" }, \
+ { XLOG_UNMOUNT_REC_TYPE, "UNMOUNT" }
+
+/*
+ * This structure is used to track log items associated with
+ * a transaction. It points to the log item and keeps some
+ * flags to track the state of the log item. It also tracks
+ * the amount of space needed to log the item it describes
+ * once we get to commit processing (see xfs_trans_commit()).
+ */
+struct xfs_log_item_desc {
+ struct xfs_log_item *lid_item;
+ struct list_head lid_trans;
+ unsigned char lid_flags;
+};
+
+#define XFS_LID_DIRTY 0x1
+
+/* log size calculation functions */
+int xfs_log_calc_unit_res(struct xfs_mount *mp, int unit_bytes);
+int xfs_log_calc_minimum_size(struct xfs_mount *);
+
+
+/*
+ * Values for t_flags.
+ */
+#define XFS_TRANS_DIRTY 0x01 /* something needs to be logged */
+#define XFS_TRANS_SB_DIRTY 0x02 /* superblock is modified */
+#define XFS_TRANS_PERM_LOG_RES 0x04 /* xact took a permanent log res */
+#define XFS_TRANS_SYNC 0x08 /* make commit synchronous */
+#define XFS_TRANS_DQ_DIRTY 0x10 /* at least one dquot in trx dirty */
+#define XFS_TRANS_RESERVE 0x20 /* OK to use reserved data blocks */
+#define XFS_TRANS_FREEZE_PROT 0x40 /* Transaction has elevated writer
+ count in superblock */
+/*
+ * Values for call flags parameter.
+ */
+#define XFS_TRANS_RELEASE_LOG_RES 0x4
+#define XFS_TRANS_ABORT 0x8
+
+/*
+ * Field values for xfs_trans_mod_sb.
+ */
+#define XFS_TRANS_SB_ICOUNT 0x00000001
+#define XFS_TRANS_SB_IFREE 0x00000002
+#define XFS_TRANS_SB_FDBLOCKS 0x00000004
+#define XFS_TRANS_SB_RES_FDBLOCKS 0x00000008
+#define XFS_TRANS_SB_FREXTENTS 0x00000010
+#define XFS_TRANS_SB_RES_FREXTENTS 0x00000020
+#define XFS_TRANS_SB_DBLOCKS 0x00000040
+#define XFS_TRANS_SB_AGCOUNT 0x00000080
+#define XFS_TRANS_SB_IMAXPCT 0x00000100
+#define XFS_TRANS_SB_REXTSIZE 0x00000200
+#define XFS_TRANS_SB_RBMBLOCKS 0x00000400
+#define XFS_TRANS_SB_RBLOCKS 0x00000800
+#define XFS_TRANS_SB_REXTENTS 0x00001000
+#define XFS_TRANS_SB_REXTSLOG 0x00002000
+
+/*
+ * Here we centralize the specification of XFS meta-data buffer reference count
+ * values. This determine how hard the buffer cache tries to hold onto the
+ * buffer.
+ */
+#define XFS_AGF_REF 4
+#define XFS_AGI_REF 4
+#define XFS_AGFL_REF 3
+#define XFS_INO_BTREE_REF 3
+#define XFS_ALLOC_BTREE_REF 2
+#define XFS_BMAP_BTREE_REF 2
+#define XFS_DIR_BTREE_REF 2
+#define XFS_INO_REF 2
+#define XFS_ATTR_BTREE_REF 1
+#define XFS_DQUOT_REF 1
+
+/*
+ * Flags for xfs_trans_ichgtime().
+ */
+#define XFS_ICHGTIME_MOD 0x1 /* data fork modification timestamp */
+#define XFS_ICHGTIME_CHG 0x2 /* inode field change timestamp */
+#define XFS_ICHGTIME_CREATE 0x4 /* inode create timestamp */
+
+
+/*
+ * Symlink decoding/encoding functions
+ */
+int xfs_symlink_blocks(struct xfs_mount *mp, int pathlen);
+int xfs_symlink_hdr_set(struct xfs_mount *mp, xfs_ino_t ino, uint32_t offset,
+ uint32_t size, struct xfs_buf *bp);
+bool xfs_symlink_hdr_ok(struct xfs_mount *mp, xfs_ino_t ino, uint32_t offset,
+ uint32_t size, struct xfs_buf *bp);
+void xfs_symlink_local_to_remote(struct xfs_trans *tp, struct xfs_buf *bp,
+ struct xfs_inode *ip, struct xfs_ifork *ifp);
+
+#endif /* __XFS_SHARED_H__ */
--
1.8.3.2
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 09/32] xfs: unify directory/attribute format definitions
[not found] <1380510944-8571-1-git-send-email-david@fromorbit.com>
` (7 preceding siblings ...)
2013-09-30 3:15 ` [PATCH 08/32] xfs: create a shared header file for format-related information Dave Chinner
@ 2013-09-30 3:15 ` Dave Chinner
2013-10-14 20:44 ` Eric Sandeen
2013-10-18 20:32 ` Rich Johnston
2013-09-30 3:15 ` [PATCH 10/32] xfs: split dquot buffer operations out Dave Chinner
` (22 subsequent siblings)
31 siblings, 2 replies; 56+ messages in thread
From: Dave Chinner @ 2013-09-30 3:15 UTC (permalink / raw)
To: xfs
From: Dave Chinner <dchinner@redhat.com>
The on-disk format definitions for the directory and attribute
structures are spread across 3 header files right now, only one of
which is dedicated to defining on-disk structures and their
manipulation (xfs_dir2_format.h). Pull all the format definitions
into a single header file - xfs_da_format.h - and switch all the
code over to point at that.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
include/Makefile | 4 +-
include/libxfs.h | 6 +-
include/xfs_attr_leaf.h | 230 --------
include/xfs_attr_remote.h | 27 -
include/xfs_da_btree.h | 140 -----
include/xfs_da_format.h | 1362 +++++++++++++++++++++++++++++++++++++++++++++
include/xfs_dir2_format.h | 964 --------------------------------
7 files changed, 1368 insertions(+), 1365 deletions(-)
create mode 100644 include/xfs_da_format.h
delete mode 100644 include/xfs_dir2_format.h
diff --git a/include/Makefile b/include/Makefile
index fd2d61b..6682b9d 100644
--- a/include/Makefile
+++ b/include/Makefile
@@ -26,7 +26,9 @@ QAHFILES = libxfs.h libxlog.h \
xfs_btree_trace.h \
xfs_cksum.h \
xfs_da_btree.h \
- xfs_dinode.h xfs_dir2.h xfs_dir2_format.h \
+ xfs_da_format.h \
+ xfs_dinode.h \
+ xfs_dir2.h \
xfs_format.h \
xfs_ialloc.h \
xfs_ialloc_btree.h \
diff --git a/include/libxfs.h b/include/libxfs.h
index a5d6388..835ba37 100644
--- a/include/libxfs.h
+++ b/include/libxfs.h
@@ -47,7 +47,6 @@
#include <xfs/xfs_inum.h>
#include <xfs/xfs_sb.h>
#include <xfs/xfs_ag.h>
-#include <xfs/xfs_da_btree.h>
#include <xfs/xfs_bmap_btree.h>
#include <xfs/xfs_alloc_btree.h>
#include <xfs/xfs_ialloc_btree.h>
@@ -267,9 +266,10 @@ extern void libxfs_umount (xfs_mount_t *);
extern void libxfs_rtmount_destroy (xfs_mount_t *);
/*
- * xfs/xfs_dir2_format.h needs struct xfs_mount to be defined
+ * xfs/xfs_da_format.h needs struct xfs_mount to be defined
*/
-#include <xfs/xfs_dir2_format.h>
+#include <xfs/xfs_da_format.h>
+#include <xfs/xfs_da_btree.h>
#include <xfs/xfs_dir2.h>
/*
diff --git a/include/xfs_attr_leaf.h b/include/xfs_attr_leaf.h
index da34e64..3ec5ec0 100644
--- a/include/xfs_attr_leaf.h
+++ b/include/xfs_attr_leaf.h
@@ -19,16 +19,6 @@
#ifndef __XFS_ATTR_LEAF_H__
#define __XFS_ATTR_LEAF_H__
-/*
- * Attribute storage layout, internal structure, access macros, etc.
- *
- * Attribute lists are structured around Btrees where all the data
- * elements are in the leaf nodes. Attribute names are hashed into an int,
- * then that int is used as the index into the Btree. Since the hashval
- * of an attribute name may not be unique, we may have duplicate keys. The
- * internal links in the Btree are logical block offsets into the file.
- */
-
struct attrlist;
struct attrlist_cursor_kern;
struct xfs_attr_list_context;
@@ -38,226 +28,6 @@ struct xfs_da_state_blk;
struct xfs_inode;
struct xfs_trans;
-/*========================================================================
- * Attribute structure when equal to XFS_LBSIZE(mp) bytes.
- *========================================================================*/
-
-/*
- * This is the structure of the leaf nodes in the Btree.
- *
- * Struct leaf_entry's are packed from the top. Name/values grow from the
- * bottom but are not packed. The freemap contains run-length-encoded entries
- * for the free bytes after the leaf_entry's, but only the N largest such,
- * smaller runs are dropped. When the freemap doesn't show enough space
- * for an allocation, we compact the name/value area and try again. If we
- * still don't have enough space, then we have to split the block. The
- * name/value structs (both local and remote versions) must be 32bit aligned.
- *
- * Since we have duplicate hash keys, for each key that matches, compare
- * the actual name string. The root and intermediate node search always
- * takes the first-in-the-block key match found, so we should only have
- * to work "forw"ard. If none matches, continue with the "forw"ard leaf
- * nodes until the hash key changes or the attribute name is found.
- *
- * We store the fact that an attribute is a ROOT/USER/SECURE attribute in
- * the leaf_entry. The namespaces are independent only because we also look
- * at the namespace bit when we are looking for a matching attribute name.
- *
- * We also store an "incomplete" bit in the leaf_entry. It shows that an
- * attribute is in the middle of being created and should not be shown to
- * the user if we crash during the time that the bit is set. We clear the
- * bit when we have finished setting up the attribute. We do this because
- * we cannot create some large attributes inside a single transaction, and we
- * need some indication that we weren't finished if we crash in the middle.
- */
-#define XFS_ATTR_LEAF_MAPSIZE 3 /* how many freespace slots */
-
-typedef struct xfs_attr_leaf_map { /* RLE map of free bytes */
- __be16 base; /* base of free region */
- __be16 size; /* length of free region */
-} xfs_attr_leaf_map_t;
-
-typedef struct xfs_attr_leaf_hdr { /* constant-structure header block */
- xfs_da_blkinfo_t info; /* block type, links, etc. */
- __be16 count; /* count of active leaf_entry's */
- __be16 usedbytes; /* num bytes of names/values stored */
- __be16 firstused; /* first used byte in name area */
- __u8 holes; /* != 0 if blk needs compaction */
- __u8 pad1;
- xfs_attr_leaf_map_t freemap[XFS_ATTR_LEAF_MAPSIZE];
- /* N largest free regions */
-} xfs_attr_leaf_hdr_t;
-
-typedef struct xfs_attr_leaf_entry { /* sorted on key, not name */
- __be32 hashval; /* hash value of name */
- __be16 nameidx; /* index into buffer of name/value */
- __u8 flags; /* LOCAL/ROOT/SECURE/INCOMPLETE flag */
- __u8 pad2; /* unused pad byte */
-} xfs_attr_leaf_entry_t;
-
-typedef struct xfs_attr_leaf_name_local {
- __be16 valuelen; /* number of bytes in value */
- __u8 namelen; /* length of name bytes */
- __u8 nameval[1]; /* name/value bytes */
-} xfs_attr_leaf_name_local_t;
-
-typedef struct xfs_attr_leaf_name_remote {
- __be32 valueblk; /* block number of value bytes */
- __be32 valuelen; /* number of bytes in value */
- __u8 namelen; /* length of name bytes */
- __u8 name[1]; /* name bytes */
-} xfs_attr_leaf_name_remote_t;
-
-typedef struct xfs_attr_leafblock {
- xfs_attr_leaf_hdr_t hdr; /* constant-structure header block */
- xfs_attr_leaf_entry_t entries[1]; /* sorted on key, not name */
- xfs_attr_leaf_name_local_t namelist; /* grows from bottom of buf */
- xfs_attr_leaf_name_remote_t valuelist; /* grows from bottom of buf */
-} xfs_attr_leafblock_t;
-
-/*
- * CRC enabled leaf structures. Called "version 3" structures to match the
- * version number of the directory and dablk structures for this feature, and
- * attr2 is already taken by the variable inode attribute fork size feature.
- */
-struct xfs_attr3_leaf_hdr {
- struct xfs_da3_blkinfo info;
- __be16 count;
- __be16 usedbytes;
- __be16 firstused;
- __u8 holes;
- __u8 pad1;
- struct xfs_attr_leaf_map freemap[XFS_ATTR_LEAF_MAPSIZE];
- __be32 pad2; /* 64 bit alignment */
-};
-
-#define XFS_ATTR3_LEAF_CRC_OFF (offsetof(struct xfs_attr3_leaf_hdr, info.crc))
-
-struct xfs_attr3_leafblock {
- struct xfs_attr3_leaf_hdr hdr;
- struct xfs_attr_leaf_entry entries[1];
-
- /*
- * The rest of the block contains the following structures after the
- * leaf entries, growing from the bottom up. The variables are never
- * referenced, the locations accessed purely from helper functions.
- *
- * struct xfs_attr_leaf_name_local
- * struct xfs_attr_leaf_name_remote
- */
-};
-
-/*
- * incore, neutral version of the attribute leaf header
- */
-struct xfs_attr3_icleaf_hdr {
- __uint32_t forw;
- __uint32_t back;
- __uint16_t magic;
- __uint16_t count;
- __uint16_t usedbytes;
- __uint16_t firstused;
- __u8 holes;
- struct {
- __uint16_t base;
- __uint16_t size;
- } freemap[XFS_ATTR_LEAF_MAPSIZE];
-};
-
-/*
- * Flags used in the leaf_entry[i].flags field.
- * NOTE: the INCOMPLETE bit must not collide with the flags bits specified
- * on the system call, they are "or"ed together for various operations.
- */
-#define XFS_ATTR_LOCAL_BIT 0 /* attr is stored locally */
-#define XFS_ATTR_ROOT_BIT 1 /* limit access to trusted attrs */
-#define XFS_ATTR_SECURE_BIT 2 /* limit access to secure attrs */
-#define XFS_ATTR_INCOMPLETE_BIT 7 /* attr in middle of create/delete */
-#define XFS_ATTR_LOCAL (1 << XFS_ATTR_LOCAL_BIT)
-#define XFS_ATTR_ROOT (1 << XFS_ATTR_ROOT_BIT)
-#define XFS_ATTR_SECURE (1 << XFS_ATTR_SECURE_BIT)
-#define XFS_ATTR_INCOMPLETE (1 << XFS_ATTR_INCOMPLETE_BIT)
-
-/*
- * Conversion macros for converting namespace bits from argument flags
- * to ondisk flags.
- */
-#define XFS_ATTR_NSP_ARGS_MASK (ATTR_ROOT | ATTR_SECURE)
-#define XFS_ATTR_NSP_ONDISK_MASK (XFS_ATTR_ROOT | XFS_ATTR_SECURE)
-#define XFS_ATTR_NSP_ONDISK(flags) ((flags) & XFS_ATTR_NSP_ONDISK_MASK)
-#define XFS_ATTR_NSP_ARGS(flags) ((flags) & XFS_ATTR_NSP_ARGS_MASK)
-#define XFS_ATTR_NSP_ARGS_TO_ONDISK(x) (((x) & ATTR_ROOT ? XFS_ATTR_ROOT : 0) |\
- ((x) & ATTR_SECURE ? XFS_ATTR_SECURE : 0))
-#define XFS_ATTR_NSP_ONDISK_TO_ARGS(x) (((x) & XFS_ATTR_ROOT ? ATTR_ROOT : 0) |\
- ((x) & XFS_ATTR_SECURE ? ATTR_SECURE : 0))
-
-/*
- * Alignment for namelist and valuelist entries (since they are mixed
- * there can be only one alignment value)
- */
-#define XFS_ATTR_LEAF_NAME_ALIGN ((uint)sizeof(xfs_dablk_t))
-
-static inline int
-xfs_attr3_leaf_hdr_size(struct xfs_attr_leafblock *leafp)
-{
- if (leafp->hdr.info.magic == cpu_to_be16(XFS_ATTR3_LEAF_MAGIC))
- return sizeof(struct xfs_attr3_leaf_hdr);
- return sizeof(struct xfs_attr_leaf_hdr);
-}
-
-static inline struct xfs_attr_leaf_entry *
-xfs_attr3_leaf_entryp(xfs_attr_leafblock_t *leafp)
-{
- if (leafp->hdr.info.magic == cpu_to_be16(XFS_ATTR3_LEAF_MAGIC))
- return &((struct xfs_attr3_leafblock *)leafp)->entries[0];
- return &leafp->entries[0];
-}
-
-/*
- * Cast typed pointers for "local" and "remote" name/value structs.
- */
-static inline char *
-xfs_attr3_leaf_name(xfs_attr_leafblock_t *leafp, int idx)
-{
- struct xfs_attr_leaf_entry *entries = xfs_attr3_leaf_entryp(leafp);
-
- return &((char *)leafp)[be16_to_cpu(entries[idx].nameidx)];
-}
-
-static inline xfs_attr_leaf_name_remote_t *
-xfs_attr3_leaf_name_remote(xfs_attr_leafblock_t *leafp, int idx)
-{
- return (xfs_attr_leaf_name_remote_t *)xfs_attr3_leaf_name(leafp, idx);
-}
-
-static inline xfs_attr_leaf_name_local_t *
-xfs_attr3_leaf_name_local(xfs_attr_leafblock_t *leafp, int idx)
-{
- return (xfs_attr_leaf_name_local_t *)xfs_attr3_leaf_name(leafp, idx);
-}
-
-/*
- * Calculate total bytes used (including trailing pad for alignment) for
- * a "local" name/value structure, a "remote" name/value structure, and
- * a pointer which might be either.
- */
-static inline int xfs_attr_leaf_entsize_remote(int nlen)
-{
- return ((uint)sizeof(xfs_attr_leaf_name_remote_t) - 1 + (nlen) + \
- XFS_ATTR_LEAF_NAME_ALIGN - 1) & ~(XFS_ATTR_LEAF_NAME_ALIGN - 1);
-}
-
-static inline int xfs_attr_leaf_entsize_local(int nlen, int vlen)
-{
- return ((uint)sizeof(xfs_attr_leaf_name_local_t) - 1 + (nlen) + (vlen) +
- XFS_ATTR_LEAF_NAME_ALIGN - 1) & ~(XFS_ATTR_LEAF_NAME_ALIGN - 1);
-}
-
-static inline int xfs_attr_leaf_entsize_local_max(int bsize)
-{
- return (((bsize) >> 1) + ((bsize) >> 2));
-}
-
/*
* Used to keep a list of "remote value" extents when unlinking an inode.
*/
diff --git a/include/xfs_attr_remote.h b/include/xfs_attr_remote.h
index b3e1e1b..5a9acfa 100644
--- a/include/xfs_attr_remote.h
+++ b/include/xfs_attr_remote.h
@@ -18,33 +18,6 @@
#ifndef __XFS_ATTR_REMOTE_H__
#define __XFS_ATTR_REMOTE_H__
-#define XFS_ATTR3_RMT_MAGIC 0x5841524d /* XARM */
-
-/*
- * There is one of these headers per filesystem block in a remote attribute.
- * This is done to ensure there is a 1:1 mapping between the attribute value
- * length and the number of blocks needed to store the attribute. This makes the
- * verification of a buffer a little more complex, but greatly simplifies the
- * allocation, reading and writing of these attributes as we don't have to guess
- * the number of blocks needed to store the attribute data.
- */
-struct xfs_attr3_rmt_hdr {
- __be32 rm_magic;
- __be32 rm_offset;
- __be32 rm_bytes;
- __be32 rm_crc;
- uuid_t rm_uuid;
- __be64 rm_owner;
- __be64 rm_blkno;
- __be64 rm_lsn;
-};
-
-#define XFS_ATTR3_RMT_CRC_OFF offsetof(struct xfs_attr3_rmt_hdr, rm_crc)
-
-#define XFS_ATTR3_RMT_BUF_SPACE(mp, bufsize) \
- ((bufsize) - (xfs_sb_version_hascrc(&(mp)->m_sb) ? \
- sizeof(struct xfs_attr3_rmt_hdr) : 0))
-
int xfs_attr3_rmt_blocks(struct xfs_mount *mp, int attrlen);
int xfs_attr_rmtval_get(struct xfs_da_args *args);
diff --git a/include/xfs_da_btree.h b/include/xfs_da_btree.h
index a762cfa..e492dca 100644
--- a/include/xfs_da_btree.h
+++ b/include/xfs_da_btree.h
@@ -25,146 +25,6 @@ struct xfs_trans;
struct zone;
/*========================================================================
- * Directory Structure when greater than XFS_LBSIZE(mp) bytes.
- *========================================================================*/
-
-/*
- * This structure is common to both leaf nodes and non-leaf nodes in the Btree.
- *
- * It is used to manage a doubly linked list of all blocks at the same
- * level in the Btree, and to identify which type of block this is.
- */
-#define XFS_DA_NODE_MAGIC 0xfebe /* magic number: non-leaf blocks */
-#define XFS_ATTR_LEAF_MAGIC 0xfbee /* magic number: attribute leaf blks */
-#define XFS_DIR2_LEAF1_MAGIC 0xd2f1 /* magic number: v2 dirlf single blks */
-#define XFS_DIR2_LEAFN_MAGIC 0xd2ff /* magic number: v2 dirlf multi blks */
-
-typedef struct xfs_da_blkinfo {
- __be32 forw; /* previous block in list */
- __be32 back; /* following block in list */
- __be16 magic; /* validity check on block */
- __be16 pad; /* unused */
-} xfs_da_blkinfo_t;
-
-/*
- * CRC enabled directory structure types
- *
- * The headers change size for the additional verification information, but
- * otherwise the tree layouts and contents are unchanged. Hence the da btree
- * code can use the struct xfs_da_blkinfo for manipulating the tree links and
- * magic numbers without modification for both v2 and v3 nodes.
- */
-#define XFS_DA3_NODE_MAGIC 0x3ebe /* magic number: non-leaf blocks */
-#define XFS_ATTR3_LEAF_MAGIC 0x3bee /* magic number: attribute leaf blks */
-#define XFS_DIR3_LEAF1_MAGIC 0x3df1 /* magic number: v2 dirlf single blks */
-#define XFS_DIR3_LEAFN_MAGIC 0x3dff /* magic number: v2 dirlf multi blks */
-
-struct xfs_da3_blkinfo {
- /*
- * the node link manipulation code relies on the fact that the first
- * element of this structure is the struct xfs_da_blkinfo so it can
- * ignore the differences in the rest of the structures.
- */
- struct xfs_da_blkinfo hdr;
- __be32 crc; /* CRC of block */
- __be64 blkno; /* first block of the buffer */
- __be64 lsn; /* sequence number of last write */
- uuid_t uuid; /* filesystem we belong to */
- __be64 owner; /* inode that owns the block */
-};
-
-/*
- * This is the structure of the root and intermediate nodes in the Btree.
- * The leaf nodes are defined above.
- *
- * Entries are not packed.
- *
- * Since we have duplicate keys, use a binary search but always follow
- * all match in the block, not just the first match found.
- */
-#define XFS_DA_NODE_MAXDEPTH 5 /* max depth of Btree */
-
-typedef struct xfs_da_node_hdr {
- struct xfs_da_blkinfo info; /* block type, links, etc. */
- __be16 __count; /* count of active entries */
- __be16 __level; /* level above leaves (leaf == 0) */
-} xfs_da_node_hdr_t;
-
-struct xfs_da3_node_hdr {
- struct xfs_da3_blkinfo info; /* block type, links, etc. */
- __be16 __count; /* count of active entries */
- __be16 __level; /* level above leaves (leaf == 0) */
- __be32 __pad32;
-};
-
-#define XFS_DA3_NODE_CRC_OFF (offsetof(struct xfs_da3_node_hdr, info.crc))
-
-typedef struct xfs_da_node_entry {
- __be32 hashval; /* hash value for this descendant */
- __be32 before; /* Btree block before this key */
-} xfs_da_node_entry_t;
-
-typedef struct xfs_da_intnode {
- struct xfs_da_node_hdr hdr;
- struct xfs_da_node_entry __btree[];
-} xfs_da_intnode_t;
-
-struct xfs_da3_intnode {
- struct xfs_da3_node_hdr hdr;
- struct xfs_da_node_entry __btree[];
-};
-
-/*
- * In-core version of the node header to abstract the differences in the v2 and
- * v3 disk format of the headers. Callers need to convert to/from disk format as
- * appropriate.
- */
-struct xfs_da3_icnode_hdr {
- __uint32_t forw;
- __uint32_t back;
- __uint16_t magic;
- __uint16_t count;
- __uint16_t level;
-};
-
-extern void xfs_da3_node_hdr_from_disk(struct xfs_da3_icnode_hdr *to,
- struct xfs_da_intnode *from);
-extern void xfs_da3_node_hdr_to_disk(struct xfs_da_intnode *to,
- struct xfs_da3_icnode_hdr *from);
-
-static inline int
-__xfs_da3_node_hdr_size(bool v3)
-{
- if (v3)
- return sizeof(struct xfs_da3_node_hdr);
- return sizeof(struct xfs_da_node_hdr);
-}
-static inline int
-xfs_da3_node_hdr_size(struct xfs_da_intnode *dap)
-{
- bool v3 = dap->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC);
-
- return __xfs_da3_node_hdr_size(v3);
-}
-
-static inline struct xfs_da_node_entry *
-xfs_da3_node_tree_p(struct xfs_da_intnode *dap)
-{
- if (dap->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC)) {
- struct xfs_da3_intnode *dap3 = (struct xfs_da3_intnode *)dap;
- return dap3->__btree;
- }
- return dap->__btree;
-}
-
-extern void xfs_da3_intnode_from_disk(struct xfs_da3_icnode_hdr *to,
- struct xfs_da_intnode *from);
-extern void xfs_da3_intnode_to_disk(struct xfs_da_intnode *to,
- struct xfs_da3_icnode_hdr *from);
-
-#define XFS_LBSIZE(mp) (mp)->m_sb.sb_blocksize
-
-/*========================================================================
* Btree searching and modification structure definitions.
*========================================================================*/
diff --git a/include/xfs_da_format.h b/include/xfs_da_format.h
new file mode 100644
index 0000000..89a1a21
--- /dev/null
+++ b/include/xfs_da_format.h
@@ -0,0 +1,1362 @@
+/*
+ * Copyright (c) 2000-2001,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
+ */
+#ifndef __XFS_DA_FORMAT_H__
+#define __XFS_DA_FORMAT_H__
+
+/*========================================================================
+ * Directory Structure when greater than XFS_LBSIZE(mp) bytes.
+ *========================================================================*/
+
+/*
+ * This structure is common to both leaf nodes and non-leaf nodes in the Btree.
+ *
+ * It is used to manage a doubly linked list of all blocks at the same
+ * level in the Btree, and to identify which type of block this is.
+ */
+#define XFS_DA_NODE_MAGIC 0xfebe /* magic number: non-leaf blocks */
+#define XFS_ATTR_LEAF_MAGIC 0xfbee /* magic number: attribute leaf blks */
+#define XFS_DIR2_LEAF1_MAGIC 0xd2f1 /* magic number: v2 dirlf single blks */
+#define XFS_DIR2_LEAFN_MAGIC 0xd2ff /* magic number: v2 dirlf multi blks */
+
+typedef struct xfs_da_blkinfo {
+ __be32 forw; /* previous block in list */
+ __be32 back; /* following block in list */
+ __be16 magic; /* validity check on block */
+ __be16 pad; /* unused */
+} xfs_da_blkinfo_t;
+
+/*
+ * CRC enabled directory structure types
+ *
+ * The headers change size for the additional verification information, but
+ * otherwise the tree layouts and contents are unchanged. Hence the da btree
+ * code can use the struct xfs_da_blkinfo for manipulating the tree links and
+ * magic numbers without modification for both v2 and v3 nodes.
+ */
+#define XFS_DA3_NODE_MAGIC 0x3ebe /* magic number: non-leaf blocks */
+#define XFS_ATTR3_LEAF_MAGIC 0x3bee /* magic number: attribute leaf blks */
+#define XFS_DIR3_LEAF1_MAGIC 0x3df1 /* magic number: v2 dirlf single blks */
+#define XFS_DIR3_LEAFN_MAGIC 0x3dff /* magic number: v2 dirlf multi blks */
+
+struct xfs_da3_blkinfo {
+ /*
+ * the node link manipulation code relies on the fact that the first
+ * element of this structure is the struct xfs_da_blkinfo so it can
+ * ignore the differences in the rest of the structures.
+ */
+ struct xfs_da_blkinfo hdr;
+ __be32 crc; /* CRC of block */
+ __be64 blkno; /* first block of the buffer */
+ __be64 lsn; /* sequence number of last write */
+ uuid_t uuid; /* filesystem we belong to */
+ __be64 owner; /* inode that owns the block */
+};
+
+/*
+ * This is the structure of the root and intermediate nodes in the Btree.
+ * The leaf nodes are defined above.
+ *
+ * Entries are not packed.
+ *
+ * Since we have duplicate keys, use a binary search but always follow
+ * all match in the block, not just the first match found.
+ */
+#define XFS_DA_NODE_MAXDEPTH 5 /* max depth of Btree */
+
+typedef struct xfs_da_node_hdr {
+ struct xfs_da_blkinfo info; /* block type, links, etc. */
+ __be16 __count; /* count of active entries */
+ __be16 __level; /* level above leaves (leaf == 0) */
+} xfs_da_node_hdr_t;
+
+struct xfs_da3_node_hdr {
+ struct xfs_da3_blkinfo info; /* block type, links, etc. */
+ __be16 __count; /* count of active entries */
+ __be16 __level; /* level above leaves (leaf == 0) */
+ __be32 __pad32;
+};
+
+#define XFS_DA3_NODE_CRC_OFF (offsetof(struct xfs_da3_node_hdr, info.crc))
+
+typedef struct xfs_da_node_entry {
+ __be32 hashval; /* hash value for this descendant */
+ __be32 before; /* Btree block before this key */
+} xfs_da_node_entry_t;
+
+typedef struct xfs_da_intnode {
+ struct xfs_da_node_hdr hdr;
+ struct xfs_da_node_entry __btree[];
+} xfs_da_intnode_t;
+
+struct xfs_da3_intnode {
+ struct xfs_da3_node_hdr hdr;
+ struct xfs_da_node_entry __btree[];
+};
+
+/*
+ * In-core version of the node header to abstract the differences in the v2 and
+ * v3 disk format of the headers. Callers need to convert to/from disk format as
+ * appropriate.
+ */
+struct xfs_da3_icnode_hdr {
+ __uint32_t forw;
+ __uint32_t back;
+ __uint16_t magic;
+ __uint16_t count;
+ __uint16_t level;
+};
+
+extern void xfs_da3_node_hdr_from_disk(struct xfs_da3_icnode_hdr *to,
+ struct xfs_da_intnode *from);
+extern void xfs_da3_node_hdr_to_disk(struct xfs_da_intnode *to,
+ struct xfs_da3_icnode_hdr *from);
+
+static inline int
+__xfs_da3_node_hdr_size(bool v3)
+{
+ if (v3)
+ return sizeof(struct xfs_da3_node_hdr);
+ return sizeof(struct xfs_da_node_hdr);
+}
+static inline int
+xfs_da3_node_hdr_size(struct xfs_da_intnode *dap)
+{
+ bool v3 = dap->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC);
+
+ return __xfs_da3_node_hdr_size(v3);
+}
+
+static inline struct xfs_da_node_entry *
+xfs_da3_node_tree_p(struct xfs_da_intnode *dap)
+{
+ if (dap->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC)) {
+ struct xfs_da3_intnode *dap3 = (struct xfs_da3_intnode *)dap;
+ return dap3->__btree;
+ }
+ return dap->__btree;
+}
+
+extern void xfs_da3_intnode_from_disk(struct xfs_da3_icnode_hdr *to,
+ struct xfs_da_intnode *from);
+extern void xfs_da3_intnode_to_disk(struct xfs_da_intnode *to,
+ struct xfs_da3_icnode_hdr *from);
+
+#define XFS_LBSIZE(mp) (mp)->m_sb.sb_blocksize
+
+/*
+ * Directory version 2.
+ *
+ * There are 4 possible formats:
+ * - shortform - embedded into the inode
+ * - single block - data with embedded leaf at the end
+ * - multiple data blocks, single leaf+freeindex block
+ * - data blocks, node and leaf blocks (btree), freeindex blocks
+ *
+ * Note: many node blocks structures and constants are shared with the attr
+ * code and defined in xfs_da_btree.h.
+ */
+
+#define XFS_DIR2_BLOCK_MAGIC 0x58443242 /* XD2B: single block dirs */
+#define XFS_DIR2_DATA_MAGIC 0x58443244 /* XD2D: multiblock dirs */
+#define XFS_DIR2_FREE_MAGIC 0x58443246 /* XD2F: free index blocks */
+
+/*
+ * Directory Version 3 With CRCs.
+ *
+ * The tree formats are the same as for version 2 directories. The difference
+ * is in the block header and dirent formats. In many cases the v3 structures
+ * use v2 definitions as they are no different and this makes code sharing much
+ * easier.
+ *
+ * Also, the xfs_dir3_*() functions handle both v2 and v3 formats - if the
+ * format is v2 then they switch to the existing v2 code, or the format is v3
+ * they implement the v3 functionality. This means the existing dir2 is a mix of
+ * xfs_dir2/xfs_dir3 calls and functions. The xfs_dir3 functions are called
+ * where there is a difference in the formats, otherwise the code is unchanged.
+ *
+ * Where it is possible, the code decides what to do based on the magic numbers
+ * in the blocks rather than feature bits in the superblock. This means the code
+ * is as independent of the external XFS code as possible as doesn't require
+ * passing struct xfs_mount pointers into places where it isn't really
+ * necessary.
+ *
+ * Version 3 includes:
+ *
+ * - a larger block header for CRC and identification purposes and so the
+ * offsets of all the structures inside the blocks are different.
+ *
+ * - new magic numbers to be able to detect the v2/v3 types on the fly.
+ */
+
+#define XFS_DIR3_BLOCK_MAGIC 0x58444233 /* XDB3: single block dirs */
+#define XFS_DIR3_DATA_MAGIC 0x58444433 /* XDD3: multiblock dirs */
+#define XFS_DIR3_FREE_MAGIC 0x58444633 /* XDF3: free index blocks */
+
+/*
+ * Dirents in version 3 directories have a file type field. Additions to this
+ * list are an on-disk format change, requiring feature bits. Valid values
+ * are as follows:
+ */
+#define XFS_DIR3_FT_UNKNOWN 0
+#define XFS_DIR3_FT_REG_FILE 1
+#define XFS_DIR3_FT_DIR 2
+#define XFS_DIR3_FT_CHRDEV 3
+#define XFS_DIR3_FT_BLKDEV 4
+#define XFS_DIR3_FT_FIFO 5
+#define XFS_DIR3_FT_SOCK 6
+#define XFS_DIR3_FT_SYMLINK 7
+#define XFS_DIR3_FT_WHT 8
+
+#define XFS_DIR3_FT_MAX 9
+
+/*
+ * Byte offset in data block and shortform entry.
+ */
+typedef __uint16_t xfs_dir2_data_off_t;
+#define NULLDATAOFF 0xffffU
+typedef uint xfs_dir2_data_aoff_t; /* argument form */
+
+/*
+ * Normalized offset (in a data block) of the entry, really xfs_dir2_data_off_t.
+ * Only need 16 bits, this is the byte offset into the single block form.
+ */
+typedef struct { __uint8_t i[2]; } __arch_pack xfs_dir2_sf_off_t;
+
+/*
+ * Offset in data space of a data entry.
+ */
+typedef __uint32_t xfs_dir2_dataptr_t;
+#define XFS_DIR2_MAX_DATAPTR ((xfs_dir2_dataptr_t)0xffffffff)
+#define XFS_DIR2_NULL_DATAPTR ((xfs_dir2_dataptr_t)0)
+
+/*
+ * Byte offset in a directory.
+ */
+typedef xfs_off_t xfs_dir2_off_t;
+
+/*
+ * Directory block number (logical dirblk in file)
+ */
+typedef __uint32_t xfs_dir2_db_t;
+
+/*
+ * Inode number stored as 8 8-bit values.
+ */
+typedef struct { __uint8_t i[8]; } xfs_dir2_ino8_t;
+
+/*
+ * Inode number stored as 4 8-bit values.
+ * Works a lot of the time, when all the inode numbers in a directory
+ * fit in 32 bits.
+ */
+typedef struct { __uint8_t i[4]; } xfs_dir2_ino4_t;
+
+typedef union {
+ xfs_dir2_ino8_t i8;
+ xfs_dir2_ino4_t i4;
+} xfs_dir2_inou_t;
+#define XFS_DIR2_MAX_SHORT_INUM ((xfs_ino_t)0xffffffffULL)
+
+/*
+ * Directory layout when stored internal to an inode.
+ *
+ * Small directories are packed as tightly as possible so as to fit into the
+ * literal area of the inode. These "shortform" directories consist of a
+ * single xfs_dir2_sf_hdr header followed by zero or more xfs_dir2_sf_entry
+ * structures. Due the different inode number storage size and the variable
+ * length name field in the xfs_dir2_sf_entry all these structure are
+ * variable length, and the accessors in this file should be used to iterate
+ * over them.
+ */
+typedef struct xfs_dir2_sf_hdr {
+ __uint8_t count; /* count of entries */
+ __uint8_t i8count; /* count of 8-byte inode #s */
+ xfs_dir2_inou_t parent; /* parent dir inode number */
+} __arch_pack xfs_dir2_sf_hdr_t;
+
+typedef struct xfs_dir2_sf_entry {
+ __u8 namelen; /* actual name length */
+ xfs_dir2_sf_off_t offset; /* saved offset */
+ __u8 name[]; /* name, variable size */
+ /*
+ * A single byte containing the file type field follows the inode
+ * number for version 3 directory entries.
+ *
+ * A xfs_dir2_ino8_t or xfs_dir2_ino4_t follows here, at a
+ * variable offset after the name.
+ */
+} __arch_pack xfs_dir2_sf_entry_t;
+
+static inline int xfs_dir2_sf_hdr_size(int i8count)
+{
+ return sizeof(struct xfs_dir2_sf_hdr) -
+ (i8count == 0) *
+ (sizeof(xfs_dir2_ino8_t) - sizeof(xfs_dir2_ino4_t));
+}
+
+static inline xfs_dir2_data_aoff_t
+xfs_dir2_sf_get_offset(xfs_dir2_sf_entry_t *sfep)
+{
+ return get_unaligned_be16(&sfep->offset.i);
+}
+
+static inline void
+xfs_dir2_sf_put_offset(xfs_dir2_sf_entry_t *sfep, xfs_dir2_data_aoff_t off)
+{
+ put_unaligned_be16(off, &sfep->offset.i);
+}
+
+static inline struct xfs_dir2_sf_entry *
+xfs_dir2_sf_firstentry(struct xfs_dir2_sf_hdr *hdr)
+{
+ return (struct xfs_dir2_sf_entry *)
+ ((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
+ * offset after the inode number. Because it's only a single byte, endian
+ * conversion is not necessary.
+ */
+static inline __uint8_t *
+xfs_dir3_sfe_ftypep(
+ struct xfs_dir2_sf_hdr *hdr,
+ struct xfs_dir2_sf_entry *sfep)
+{
+ return (__uint8_t *)&sfep->name[sfep->namelen];
+}
+
+static inline __uint8_t
+xfs_dir3_sfe_get_ftype(
+ struct xfs_mount *mp,
+ struct xfs_dir2_sf_hdr *hdr,
+ struct xfs_dir2_sf_entry *sfep)
+{
+ __uint8_t *ftp;
+
+ if (!xfs_sb_version_hasftype(&mp->m_sb))
+ return XFS_DIR3_FT_UNKNOWN;
+
+ ftp = xfs_dir3_sfe_ftypep(hdr, sfep);
+ if (*ftp >= XFS_DIR3_FT_MAX)
+ return XFS_DIR3_FT_UNKNOWN;
+ return *ftp;
+}
+
+static inline void
+xfs_dir3_sfe_put_ftype(
+ struct xfs_mount *mp,
+ struct xfs_dir2_sf_hdr *hdr,
+ struct xfs_dir2_sf_entry *sfep,
+ __uint8_t ftype)
+{
+ __uint8_t *ftp;
+
+ ASSERT(ftype < XFS_DIR3_FT_MAX);
+
+ if (!xfs_sb_version_hasftype(&mp->m_sb))
+ return;
+ ftp = xfs_dir3_sfe_ftypep(hdr, sfep);
+ *ftp = ftype;
+}
+
+/*
+ * Data block structures.
+ *
+ * A pure data block looks like the following drawing on disk:
+ *
+ * +-------------------------------------------------+
+ * | xfs_dir2_data_hdr_t |
+ * +-------------------------------------------------+
+ * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t |
+ * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t |
+ * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t |
+ * | ... |
+ * +-------------------------------------------------+
+ * | unused space |
+ * +-------------------------------------------------+
+ *
+ * As all the entries are variable size structures the accessors below should
+ * be used to iterate over them.
+ *
+ * In addition to the pure data blocks for the data and node formats,
+ * most structures are also used for the combined data/freespace "block"
+ * format below.
+ */
+
+#define XFS_DIR2_DATA_ALIGN_LOG 3 /* i.e., 8 bytes */
+#define XFS_DIR2_DATA_ALIGN (1 << XFS_DIR2_DATA_ALIGN_LOG)
+#define XFS_DIR2_DATA_FREE_TAG 0xffff
+#define XFS_DIR2_DATA_FD_COUNT 3
+
+/*
+ * Directory address space divided into sections,
+ * spaces separated by 32GB.
+ */
+#define XFS_DIR2_SPACE_SIZE (1ULL << (32 + XFS_DIR2_DATA_ALIGN_LOG))
+#define XFS_DIR2_DATA_SPACE 0
+#define XFS_DIR2_DATA_OFFSET (XFS_DIR2_DATA_SPACE * XFS_DIR2_SPACE_SIZE)
+#define XFS_DIR2_DATA_FIRSTDB(mp) \
+ xfs_dir2_byte_to_db(mp, XFS_DIR2_DATA_OFFSET)
+
+/*
+ * Describe a free area in the data block.
+ *
+ * The freespace will be formatted as a xfs_dir2_data_unused_t.
+ */
+typedef struct xfs_dir2_data_free {
+ __be16 offset; /* start of freespace */
+ __be16 length; /* length of freespace */
+} xfs_dir2_data_free_t;
+
+/*
+ * Header for the data blocks.
+ *
+ * The code knows that XFS_DIR2_DATA_FD_COUNT is 3.
+ */
+typedef struct xfs_dir2_data_hdr {
+ __be32 magic; /* XFS_DIR2_DATA_MAGIC or */
+ /* XFS_DIR2_BLOCK_MAGIC */
+ xfs_dir2_data_free_t bestfree[XFS_DIR2_DATA_FD_COUNT];
+} xfs_dir2_data_hdr_t;
+
+/*
+ * define a structure for all the verification fields we are adding to the
+ * directory block structures. This will be used in several structures.
+ * The magic number must be the first entry to align with all the dir2
+ * structures so we determine how to decode them just by the magic number.
+ */
+struct xfs_dir3_blk_hdr {
+ __be32 magic; /* magic number */
+ __be32 crc; /* CRC of block */
+ __be64 blkno; /* first block of the buffer */
+ __be64 lsn; /* sequence number of last write */
+ uuid_t uuid; /* filesystem we belong to */
+ __be64 owner; /* inode that owns the block */
+};
+
+struct xfs_dir3_data_hdr {
+ struct xfs_dir3_blk_hdr hdr;
+ xfs_dir2_data_free_t best_free[XFS_DIR2_DATA_FD_COUNT];
+ __be32 pad; /* 64 bit alignment */
+};
+
+#define XFS_DIR3_DATA_CRC_OFF offsetof(struct xfs_dir3_data_hdr, hdr.crc)
+
+static inline struct xfs_dir2_data_free *
+xfs_dir3_data_bestfree_p(struct xfs_dir2_data_hdr *hdr)
+{
+ if (hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
+ hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) {
+ struct xfs_dir3_data_hdr *hdr3 = (struct xfs_dir3_data_hdr *)hdr;
+ return hdr3->best_free;
+ }
+ return hdr->bestfree;
+}
+
+/*
+ * Active entry in a data block.
+ *
+ * Aligned to 8 bytes. After the variable length name field there is a
+ * 2 byte tag field, which can be accessed using xfs_dir3_data_entry_tag_p.
+ *
+ * For dir3 structures, there is file type field between the name and the tag.
+ * This can only be manipulated by helper functions. It is packed hard against
+ * the end of the name so any padding for rounding is between the file type and
+ * the tag.
+ */
+typedef struct xfs_dir2_data_entry {
+ __be64 inumber; /* inode number */
+ __u8 namelen; /* name length */
+ __u8 name[]; /* name bytes, no null */
+ /* __u8 filetype; */ /* type of inode we point to */
+ /* __be16 tag; */ /* starting offset of us */
+} xfs_dir2_data_entry_t;
+
+/*
+ * Unused entry in a data block.
+ *
+ * Aligned to 8 bytes. Tag appears as the last 2 bytes and must be accessed
+ * using xfs_dir2_data_unused_tag_p.
+ */
+typedef struct xfs_dir2_data_unused {
+ __be16 freetag; /* XFS_DIR2_DATA_FREE_TAG */
+ __be16 length; /* total free length */
+ /* variable offset */
+ __be16 tag; /* starting offset of us */
+} xfs_dir2_data_unused_t;
+
+/*
+ * Size of a data entry.
+ */
+static inline 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 inline int
+xfs_dir3_data_entsize(
+ struct xfs_mount *mp,
+ int n)
+{
+ bool ftype = xfs_sb_version_hasftype(&mp->m_sb) ? true : false;
+ return __xfs_dir3_data_entsize(ftype, n);
+}
+
+static inline __uint8_t
+xfs_dir3_dirent_get_ftype(
+ struct xfs_mount *mp,
+ struct xfs_dir2_data_entry *dep)
+{
+ if (xfs_sb_version_hasftype(&mp->m_sb)) {
+ __uint8_t type = dep->name[dep->namelen];
+
+ ASSERT(type < XFS_DIR3_FT_MAX);
+ if (type < XFS_DIR3_FT_MAX)
+ return type;
+
+ }
+ return XFS_DIR3_FT_UNKNOWN;
+}
+
+static inline void
+xfs_dir3_dirent_put_ftype(
+ struct xfs_mount *mp,
+ struct xfs_dir2_data_entry *dep,
+ __uint8_t type)
+{
+ ASSERT(type < XFS_DIR3_FT_MAX);
+ ASSERT(dep->namelen != 0);
+
+ if (xfs_sb_version_hasftype(&mp->m_sb))
+ dep->name[dep->namelen] = type;
+}
+
+/*
+ * Pointer to an entry's tag word.
+ */
+static inline __be16 *
+xfs_dir3_data_entry_tag_p(
+ struct xfs_mount *mp,
+ struct xfs_dir2_data_entry *dep)
+{
+ return (__be16 *)((char *)dep +
+ xfs_dir3_data_entsize(mp, dep->namelen) - sizeof(__be16));
+}
+
+/*
+ * Pointer to a freespace's tag word.
+ */
+static inline __be16 *
+xfs_dir2_data_unused_tag_p(struct xfs_dir2_data_unused *dup)
+{
+ return (__be16 *)((char *)dup +
+ be16_to_cpu(dup->length) - sizeof(__be16));
+}
+
+static inline size_t
+xfs_dir3_data_hdr_size(bool dir3)
+{
+ if (dir3)
+ return sizeof(struct xfs_dir3_data_hdr);
+ return sizeof(struct xfs_dir2_data_hdr);
+}
+
+static inline size_t
+xfs_dir3_data_entry_offset(struct xfs_dir2_data_hdr *hdr)
+{
+ bool dir3 = hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
+ hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC);
+ return xfs_dir3_data_hdr_size(dir3);
+}
+
+static inline 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(hdr));
+}
+
+static inline 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(hdr));
+}
+
+/*
+ * Offsets of . and .. in data space (always block 0)
+ *
+ * XXX: there is scope for significant optimisation of the logic here. Right
+ * now we are checking for "dir3 format" over and over again. Ideally we should
+ * only do it once for each operation.
+ */
+static inline xfs_dir2_data_aoff_t
+xfs_dir3_data_dot_offset(struct xfs_mount *mp)
+{
+ return xfs_dir3_data_hdr_size(xfs_sb_version_hascrc(&mp->m_sb));
+}
+
+static inline xfs_dir2_data_aoff_t
+xfs_dir3_data_dotdot_offset(struct xfs_mount *mp)
+{
+ return xfs_dir3_data_dot_offset(mp) +
+ xfs_dir3_data_entsize(mp, 1);
+}
+
+static inline xfs_dir2_data_aoff_t
+xfs_dir3_data_first_offset(struct xfs_mount *mp)
+{
+ return xfs_dir3_data_dotdot_offset(mp) +
+ xfs_dir3_data_entsize(mp, 2);
+}
+
+/*
+ * location of . and .. in data space (always block 0)
+ */
+static inline struct xfs_dir2_data_entry *
+xfs_dir3_data_dot_entry_p(
+ struct xfs_mount *mp,
+ struct xfs_dir2_data_hdr *hdr)
+{
+ return (struct xfs_dir2_data_entry *)
+ ((char *)hdr + xfs_dir3_data_dot_offset(mp));
+}
+
+static inline struct xfs_dir2_data_entry *
+xfs_dir3_data_dotdot_entry_p(
+ struct xfs_mount *mp,
+ struct xfs_dir2_data_hdr *hdr)
+{
+ return (struct xfs_dir2_data_entry *)
+ ((char *)hdr + xfs_dir3_data_dotdot_offset(mp));
+}
+
+static inline struct xfs_dir2_data_entry *
+xfs_dir3_data_first_entry_p(
+ struct xfs_mount *mp,
+ struct xfs_dir2_data_hdr *hdr)
+{
+ return (struct xfs_dir2_data_entry *)
+ ((char *)hdr + xfs_dir3_data_first_offset(mp));
+}
+
+/*
+ * Leaf block structures.
+ *
+ * A pure leaf block looks like the following drawing on disk:
+ *
+ * +---------------------------+
+ * | xfs_dir2_leaf_hdr_t |
+ * +---------------------------+
+ * | xfs_dir2_leaf_entry_t |
+ * | xfs_dir2_leaf_entry_t |
+ * | xfs_dir2_leaf_entry_t |
+ * | xfs_dir2_leaf_entry_t |
+ * | ... |
+ * +---------------------------+
+ * | xfs_dir2_data_off_t |
+ * | xfs_dir2_data_off_t |
+ * | xfs_dir2_data_off_t |
+ * | ... |
+ * +---------------------------+
+ * | xfs_dir2_leaf_tail_t |
+ * +---------------------------+
+ *
+ * The xfs_dir2_data_off_t members (bests) and tail are at the end of the block
+ * for single-leaf (magic = XFS_DIR2_LEAF1_MAGIC) blocks only, but not present
+ * for directories with separate leaf nodes and free space blocks
+ * (magic = XFS_DIR2_LEAFN_MAGIC).
+ *
+ * As all the entries are variable size structures the accessors below should
+ * be used to iterate over them.
+ */
+
+/*
+ * Offset of the leaf/node space. First block in this space
+ * is the btree root.
+ */
+#define XFS_DIR2_LEAF_SPACE 1
+#define XFS_DIR2_LEAF_OFFSET (XFS_DIR2_LEAF_SPACE * XFS_DIR2_SPACE_SIZE)
+#define XFS_DIR2_LEAF_FIRSTDB(mp) \
+ xfs_dir2_byte_to_db(mp, XFS_DIR2_LEAF_OFFSET)
+
+/*
+ * Leaf block header.
+ */
+typedef struct xfs_dir2_leaf_hdr {
+ xfs_da_blkinfo_t info; /* header for da routines */
+ __be16 count; /* count of entries */
+ __be16 stale; /* count of stale entries */
+} xfs_dir2_leaf_hdr_t;
+
+struct xfs_dir3_leaf_hdr {
+ struct xfs_da3_blkinfo info; /* header for da routines */
+ __be16 count; /* count of entries */
+ __be16 stale; /* count of stale entries */
+ __be32 pad; /* 64 bit alignment */
+};
+
+struct xfs_dir3_icleaf_hdr {
+ __uint32_t forw;
+ __uint32_t back;
+ __uint16_t magic;
+ __uint16_t count;
+ __uint16_t stale;
+};
+
+/*
+ * Leaf block entry.
+ */
+typedef struct xfs_dir2_leaf_entry {
+ __be32 hashval; /* hash value of name */
+ __be32 address; /* address of data entry */
+} xfs_dir2_leaf_entry_t;
+
+/*
+ * Leaf block tail.
+ */
+typedef struct xfs_dir2_leaf_tail {
+ __be32 bestcount;
+} xfs_dir2_leaf_tail_t;
+
+/*
+ * Leaf block.
+ */
+typedef struct xfs_dir2_leaf {
+ xfs_dir2_leaf_hdr_t hdr; /* leaf header */
+ xfs_dir2_leaf_entry_t __ents[]; /* entries */
+} xfs_dir2_leaf_t;
+
+struct xfs_dir3_leaf {
+ struct xfs_dir3_leaf_hdr hdr; /* leaf header */
+ struct xfs_dir2_leaf_entry __ents[]; /* entries */
+};
+
+#define XFS_DIR3_LEAF_CRC_OFF offsetof(struct xfs_dir3_leaf_hdr, info.crc)
+
+extern void xfs_dir3_leaf_hdr_from_disk(struct xfs_dir3_icleaf_hdr *to,
+ struct xfs_dir2_leaf *from);
+
+static inline int
+xfs_dir3_leaf_hdr_size(struct xfs_dir2_leaf *lp)
+{
+ if (lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) ||
+ lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC))
+ return sizeof(struct xfs_dir3_leaf_hdr);
+ return sizeof(struct xfs_dir2_leaf_hdr);
+}
+
+static inline int
+xfs_dir3_max_leaf_ents(struct xfs_mount *mp, struct xfs_dir2_leaf *lp)
+{
+ return (mp->m_dirblksize - xfs_dir3_leaf_hdr_size(lp)) /
+ (uint)sizeof(struct xfs_dir2_leaf_entry);
+}
+
+/*
+ * Get address of the bestcount field in the single-leaf block.
+ */
+static inline struct xfs_dir2_leaf_entry *
+xfs_dir3_leaf_ents_p(struct xfs_dir2_leaf *lp)
+{
+ if (lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) ||
+ lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)) {
+ struct xfs_dir3_leaf *lp3 = (struct xfs_dir3_leaf *)lp;
+ return lp3->__ents;
+ }
+ return lp->__ents;
+}
+
+/*
+ * Get address of the bestcount field in the single-leaf block.
+ */
+static inline struct xfs_dir2_leaf_tail *
+xfs_dir2_leaf_tail_p(struct xfs_mount *mp, struct xfs_dir2_leaf *lp)
+{
+ return (struct xfs_dir2_leaf_tail *)
+ ((char *)lp + mp->m_dirblksize -
+ sizeof(struct xfs_dir2_leaf_tail));
+}
+
+/*
+ * Get address of the bests array in the single-leaf block.
+ */
+static inline __be16 *
+xfs_dir2_leaf_bests_p(struct xfs_dir2_leaf_tail *ltp)
+{
+ return (__be16 *)ltp - be32_to_cpu(ltp->bestcount);
+}
+
+/*
+ * DB blocks here are logical directory block numbers, not filesystem blocks.
+ */
+
+/*
+ * Convert dataptr to byte in file space
+ */
+static inline xfs_dir2_off_t
+xfs_dir2_dataptr_to_byte(struct xfs_mount *mp, xfs_dir2_dataptr_t dp)
+{
+ return (xfs_dir2_off_t)dp << XFS_DIR2_DATA_ALIGN_LOG;
+}
+
+/*
+ * Convert byte in file space to dataptr. It had better be aligned.
+ */
+static inline xfs_dir2_dataptr_t
+xfs_dir2_byte_to_dataptr(struct xfs_mount *mp, xfs_dir2_off_t by)
+{
+ return (xfs_dir2_dataptr_t)(by >> XFS_DIR2_DATA_ALIGN_LOG);
+}
+
+/*
+ * Convert byte in space to (DB) block
+ */
+static inline xfs_dir2_db_t
+xfs_dir2_byte_to_db(struct xfs_mount *mp, xfs_dir2_off_t by)
+{
+ return (xfs_dir2_db_t)
+ (by >> (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog));
+}
+
+/*
+ * Convert dataptr to a block number
+ */
+static inline xfs_dir2_db_t
+xfs_dir2_dataptr_to_db(struct xfs_mount *mp, xfs_dir2_dataptr_t dp)
+{
+ return xfs_dir2_byte_to_db(mp, xfs_dir2_dataptr_to_byte(mp, dp));
+}
+
+/*
+ * Convert byte in space to offset in a block
+ */
+static inline xfs_dir2_data_aoff_t
+xfs_dir2_byte_to_off(struct xfs_mount *mp, xfs_dir2_off_t by)
+{
+ return (xfs_dir2_data_aoff_t)(by &
+ ((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) - 1));
+}
+
+/*
+ * Convert dataptr to a byte offset in a block
+ */
+static inline xfs_dir2_data_aoff_t
+xfs_dir2_dataptr_to_off(struct xfs_mount *mp, xfs_dir2_dataptr_t dp)
+{
+ return xfs_dir2_byte_to_off(mp, xfs_dir2_dataptr_to_byte(mp, dp));
+}
+
+/*
+ * Convert block and offset to byte in space
+ */
+static inline xfs_dir2_off_t
+xfs_dir2_db_off_to_byte(struct xfs_mount *mp, xfs_dir2_db_t db,
+ xfs_dir2_data_aoff_t o)
+{
+ return ((xfs_dir2_off_t)db <<
+ (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) + o;
+}
+
+/*
+ * Convert block (DB) to block (dablk)
+ */
+static inline xfs_dablk_t
+xfs_dir2_db_to_da(struct xfs_mount *mp, xfs_dir2_db_t db)
+{
+ return (xfs_dablk_t)(db << mp->m_sb.sb_dirblklog);
+}
+
+/*
+ * Convert byte in space to (DA) block
+ */
+static inline xfs_dablk_t
+xfs_dir2_byte_to_da(struct xfs_mount *mp, xfs_dir2_off_t by)
+{
+ return xfs_dir2_db_to_da(mp, xfs_dir2_byte_to_db(mp, by));
+}
+
+/*
+ * Convert block and offset to dataptr
+ */
+static inline xfs_dir2_dataptr_t
+xfs_dir2_db_off_to_dataptr(struct xfs_mount *mp, xfs_dir2_db_t db,
+ xfs_dir2_data_aoff_t o)
+{
+ return xfs_dir2_byte_to_dataptr(mp, xfs_dir2_db_off_to_byte(mp, db, o));
+}
+
+/*
+ * Convert block (dablk) to block (DB)
+ */
+static inline xfs_dir2_db_t
+xfs_dir2_da_to_db(struct xfs_mount *mp, xfs_dablk_t da)
+{
+ return (xfs_dir2_db_t)(da >> mp->m_sb.sb_dirblklog);
+}
+
+/*
+ * Convert block (dablk) to byte offset in space
+ */
+static inline xfs_dir2_off_t
+xfs_dir2_da_to_byte(struct xfs_mount *mp, xfs_dablk_t da)
+{
+ return xfs_dir2_db_off_to_byte(mp, xfs_dir2_da_to_db(mp, da), 0);
+}
+
+/*
+ * Free space block defintions for the node format.
+ */
+
+/*
+ * Offset of the freespace index.
+ */
+#define XFS_DIR2_FREE_SPACE 2
+#define XFS_DIR2_FREE_OFFSET (XFS_DIR2_FREE_SPACE * XFS_DIR2_SPACE_SIZE)
+#define XFS_DIR2_FREE_FIRSTDB(mp) \
+ xfs_dir2_byte_to_db(mp, XFS_DIR2_FREE_OFFSET)
+
+typedef struct xfs_dir2_free_hdr {
+ __be32 magic; /* XFS_DIR2_FREE_MAGIC */
+ __be32 firstdb; /* db of first entry */
+ __be32 nvalid; /* count of valid entries */
+ __be32 nused; /* count of used entries */
+} xfs_dir2_free_hdr_t;
+
+typedef struct xfs_dir2_free {
+ xfs_dir2_free_hdr_t hdr; /* block header */
+ __be16 bests[]; /* best free counts */
+ /* unused entries are -1 */
+} xfs_dir2_free_t;
+
+struct xfs_dir3_free_hdr {
+ struct xfs_dir3_blk_hdr hdr;
+ __be32 firstdb; /* db of first entry */
+ __be32 nvalid; /* count of valid entries */
+ __be32 nused; /* count of used entries */
+ __be32 pad; /* 64 bit alignment */
+};
+
+struct xfs_dir3_free {
+ struct xfs_dir3_free_hdr hdr;
+ __be16 bests[]; /* best free counts */
+ /* unused entries are -1 */
+};
+
+#define XFS_DIR3_FREE_CRC_OFF offsetof(struct xfs_dir3_free, hdr.hdr.crc)
+
+/*
+ * In core version of the free block header, abstracted away from on-disk format
+ * differences. Use this in the code, and convert to/from the disk version using
+ * xfs_dir3_free_hdr_from_disk/xfs_dir3_free_hdr_to_disk.
+ */
+struct xfs_dir3_icfree_hdr {
+ __uint32_t magic;
+ __uint32_t firstdb;
+ __uint32_t nvalid;
+ __uint32_t nused;
+
+};
+
+void xfs_dir3_free_hdr_from_disk(struct xfs_dir3_icfree_hdr *to,
+ struct xfs_dir2_free *from);
+
+static inline int
+xfs_dir3_free_hdr_size(struct xfs_mount *mp)
+{
+ if (xfs_sb_version_hascrc(&mp->m_sb))
+ return sizeof(struct xfs_dir3_free_hdr);
+ return sizeof(struct xfs_dir2_free_hdr);
+}
+
+static inline int
+xfs_dir3_free_max_bests(struct xfs_mount *mp)
+{
+ return (mp->m_dirblksize - xfs_dir3_free_hdr_size(mp)) /
+ sizeof(xfs_dir2_data_off_t);
+}
+
+static inline __be16 *
+xfs_dir3_free_bests_p(struct xfs_mount *mp, struct xfs_dir2_free *free)
+{
+ return (__be16 *)((char *)free + xfs_dir3_free_hdr_size(mp));
+}
+
+/*
+ * Convert data space db to the corresponding free db.
+ */
+static inline xfs_dir2_db_t
+xfs_dir2_db_to_fdb(struct xfs_mount *mp, xfs_dir2_db_t db)
+{
+ return XFS_DIR2_FREE_FIRSTDB(mp) + db / xfs_dir3_free_max_bests(mp);
+}
+
+/*
+ * Convert data space db to the corresponding index in a free db.
+ */
+static inline int
+xfs_dir2_db_to_fdindex(struct xfs_mount *mp, xfs_dir2_db_t db)
+{
+ return db % xfs_dir3_free_max_bests(mp);
+}
+
+/*
+ * Single block format.
+ *
+ * The single block format looks like the following drawing on disk:
+ *
+ * +-------------------------------------------------+
+ * | xfs_dir2_data_hdr_t |
+ * +-------------------------------------------------+
+ * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t |
+ * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t |
+ * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t :
+ * | ... |
+ * +-------------------------------------------------+
+ * | unused space |
+ * +-------------------------------------------------+
+ * | ... |
+ * | xfs_dir2_leaf_entry_t |
+ * | xfs_dir2_leaf_entry_t |
+ * +-------------------------------------------------+
+ * | xfs_dir2_block_tail_t |
+ * +-------------------------------------------------+
+ *
+ * As all the entries are variable size structures the accessors below should
+ * be used to iterate over them.
+ */
+
+typedef struct xfs_dir2_block_tail {
+ __be32 count; /* count of leaf entries */
+ __be32 stale; /* count of stale lf entries */
+} xfs_dir2_block_tail_t;
+
+/*
+ * Pointer to the leaf header embedded in a data block (1-block format)
+ */
+static inline struct xfs_dir2_block_tail *
+xfs_dir2_block_tail_p(struct xfs_mount *mp, struct xfs_dir2_data_hdr *hdr)
+{
+ return ((struct xfs_dir2_block_tail *)
+ ((char *)hdr + mp->m_dirblksize)) - 1;
+}
+
+/*
+ * Pointer to the leaf entries embedded in a data block (1-block format)
+ */
+static inline struct xfs_dir2_leaf_entry *
+xfs_dir2_block_leaf_p(struct xfs_dir2_block_tail *btp)
+{
+ return ((struct xfs_dir2_leaf_entry *)btp) - be32_to_cpu(btp->count);
+}
+
+
+/*
+ * Attribute storage layout
+ *
+ * Attribute lists are structured around Btrees where all the data
+ * elements are in the leaf nodes. Attribute names are hashed into an int,
+ * then that int is used as the index into the Btree. Since the hashval
+ * of an attribute name may not be unique, we may have duplicate keys. The
+ * internal links in the Btree are logical block offsets into the file.
+ *
+ *========================================================================
+ * Attribute structure when equal to XFS_LBSIZE(mp) bytes.
+ *========================================================================
+ *
+ * Struct leaf_entry's are packed from the top. Name/values grow from the
+ * bottom but are not packed. The freemap contains run-length-encoded entries
+ * for the free bytes after the leaf_entry's, but only the N largest such,
+ * smaller runs are dropped. When the freemap doesn't show enough space
+ * for an allocation, we compact the name/value area and try again. If we
+ * still don't have enough space, then we have to split the block. The
+ * name/value structs (both local and remote versions) must be 32bit aligned.
+ *
+ * Since we have duplicate hash keys, for each key that matches, compare
+ * the actual name string. The root and intermediate node search always
+ * takes the first-in-the-block key match found, so we should only have
+ * to work "forw"ard. If none matches, continue with the "forw"ard leaf
+ * nodes until the hash key changes or the attribute name is found.
+ *
+ * We store the fact that an attribute is a ROOT/USER/SECURE attribute in
+ * the leaf_entry. The namespaces are independent only because we also look
+ * at the namespace bit when we are looking for a matching attribute name.
+ *
+ * We also store an "incomplete" bit in the leaf_entry. It shows that an
+ * attribute is in the middle of being created and should not be shown to
+ * the user if we crash during the time that the bit is set. We clear the
+ * bit when we have finished setting up the attribute. We do this because
+ * we cannot create some large attributes inside a single transaction, and we
+ * need some indication that we weren't finished if we crash in the middle.
+ */
+#define XFS_ATTR_LEAF_MAPSIZE 3 /* how many freespace slots */
+
+typedef struct xfs_attr_leaf_map { /* RLE map of free bytes */
+ __be16 base; /* base of free region */
+ __be16 size; /* length of free region */
+} xfs_attr_leaf_map_t;
+
+typedef struct xfs_attr_leaf_hdr { /* constant-structure header block */
+ xfs_da_blkinfo_t info; /* block type, links, etc. */
+ __be16 count; /* count of active leaf_entry's */
+ __be16 usedbytes; /* num bytes of names/values stored */
+ __be16 firstused; /* first used byte in name area */
+ __u8 holes; /* != 0 if blk needs compaction */
+ __u8 pad1;
+ xfs_attr_leaf_map_t freemap[XFS_ATTR_LEAF_MAPSIZE];
+ /* N largest free regions */
+} xfs_attr_leaf_hdr_t;
+
+typedef struct xfs_attr_leaf_entry { /* sorted on key, not name */
+ __be32 hashval; /* hash value of name */
+ __be16 nameidx; /* index into buffer of name/value */
+ __u8 flags; /* LOCAL/ROOT/SECURE/INCOMPLETE flag */
+ __u8 pad2; /* unused pad byte */
+} xfs_attr_leaf_entry_t;
+
+typedef struct xfs_attr_leaf_name_local {
+ __be16 valuelen; /* number of bytes in value */
+ __u8 namelen; /* length of name bytes */
+ __u8 nameval[1]; /* name/value bytes */
+} xfs_attr_leaf_name_local_t;
+
+typedef struct xfs_attr_leaf_name_remote {
+ __be32 valueblk; /* block number of value bytes */
+ __be32 valuelen; /* number of bytes in value */
+ __u8 namelen; /* length of name bytes */
+ __u8 name[1]; /* name bytes */
+} xfs_attr_leaf_name_remote_t;
+
+typedef struct xfs_attr_leafblock {
+ xfs_attr_leaf_hdr_t hdr; /* constant-structure header block */
+ xfs_attr_leaf_entry_t entries[1]; /* sorted on key, not name */
+ xfs_attr_leaf_name_local_t namelist; /* grows from bottom of buf */
+ xfs_attr_leaf_name_remote_t valuelist; /* grows from bottom of buf */
+} xfs_attr_leafblock_t;
+
+/*
+ * CRC enabled leaf structures. Called "version 3" structures to match the
+ * version number of the directory and dablk structures for this feature, and
+ * attr2 is already taken by the variable inode attribute fork size feature.
+ */
+struct xfs_attr3_leaf_hdr {
+ struct xfs_da3_blkinfo info;
+ __be16 count;
+ __be16 usedbytes;
+ __be16 firstused;
+ __u8 holes;
+ __u8 pad1;
+ struct xfs_attr_leaf_map freemap[XFS_ATTR_LEAF_MAPSIZE];
+ __be32 pad2; /* 64 bit alignment */
+};
+
+#define XFS_ATTR3_LEAF_CRC_OFF (offsetof(struct xfs_attr3_leaf_hdr, info.crc))
+
+struct xfs_attr3_leafblock {
+ struct xfs_attr3_leaf_hdr hdr;
+ struct xfs_attr_leaf_entry entries[1];
+
+ /*
+ * The rest of the block contains the following structures after the
+ * leaf entries, growing from the bottom up. The variables are never
+ * referenced, the locations accessed purely from helper functions.
+ *
+ * struct xfs_attr_leaf_name_local
+ * struct xfs_attr_leaf_name_remote
+ */
+};
+
+/*
+ * incore, neutral version of the attribute leaf header
+ */
+struct xfs_attr3_icleaf_hdr {
+ __uint32_t forw;
+ __uint32_t back;
+ __uint16_t magic;
+ __uint16_t count;
+ __uint16_t usedbytes;
+ __uint16_t firstused;
+ __u8 holes;
+ struct {
+ __uint16_t base;
+ __uint16_t size;
+ } freemap[XFS_ATTR_LEAF_MAPSIZE];
+};
+
+/*
+ * Flags used in the leaf_entry[i].flags field.
+ * NOTE: the INCOMPLETE bit must not collide with the flags bits specified
+ * on the system call, they are "or"ed together for various operations.
+ */
+#define XFS_ATTR_LOCAL_BIT 0 /* attr is stored locally */
+#define XFS_ATTR_ROOT_BIT 1 /* limit access to trusted attrs */
+#define XFS_ATTR_SECURE_BIT 2 /* limit access to secure attrs */
+#define XFS_ATTR_INCOMPLETE_BIT 7 /* attr in middle of create/delete */
+#define XFS_ATTR_LOCAL (1 << XFS_ATTR_LOCAL_BIT)
+#define XFS_ATTR_ROOT (1 << XFS_ATTR_ROOT_BIT)
+#define XFS_ATTR_SECURE (1 << XFS_ATTR_SECURE_BIT)
+#define XFS_ATTR_INCOMPLETE (1 << XFS_ATTR_INCOMPLETE_BIT)
+
+/*
+ * Conversion macros for converting namespace bits from argument flags
+ * to ondisk flags.
+ */
+#define XFS_ATTR_NSP_ARGS_MASK (ATTR_ROOT | ATTR_SECURE)
+#define XFS_ATTR_NSP_ONDISK_MASK (XFS_ATTR_ROOT | XFS_ATTR_SECURE)
+#define XFS_ATTR_NSP_ONDISK(flags) ((flags) & XFS_ATTR_NSP_ONDISK_MASK)
+#define XFS_ATTR_NSP_ARGS(flags) ((flags) & XFS_ATTR_NSP_ARGS_MASK)
+#define XFS_ATTR_NSP_ARGS_TO_ONDISK(x) (((x) & ATTR_ROOT ? XFS_ATTR_ROOT : 0) |\
+ ((x) & ATTR_SECURE ? XFS_ATTR_SECURE : 0))
+#define XFS_ATTR_NSP_ONDISK_TO_ARGS(x) (((x) & XFS_ATTR_ROOT ? ATTR_ROOT : 0) |\
+ ((x) & XFS_ATTR_SECURE ? ATTR_SECURE : 0))
+
+/*
+ * Alignment for namelist and valuelist entries (since they are mixed
+ * there can be only one alignment value)
+ */
+#define XFS_ATTR_LEAF_NAME_ALIGN ((uint)sizeof(xfs_dablk_t))
+
+static inline int
+xfs_attr3_leaf_hdr_size(struct xfs_attr_leafblock *leafp)
+{
+ if (leafp->hdr.info.magic == cpu_to_be16(XFS_ATTR3_LEAF_MAGIC))
+ return sizeof(struct xfs_attr3_leaf_hdr);
+ return sizeof(struct xfs_attr_leaf_hdr);
+}
+
+static inline struct xfs_attr_leaf_entry *
+xfs_attr3_leaf_entryp(xfs_attr_leafblock_t *leafp)
+{
+ if (leafp->hdr.info.magic == cpu_to_be16(XFS_ATTR3_LEAF_MAGIC))
+ return &((struct xfs_attr3_leafblock *)leafp)->entries[0];
+ return &leafp->entries[0];
+}
+
+/*
+ * Cast typed pointers for "local" and "remote" name/value structs.
+ */
+static inline char *
+xfs_attr3_leaf_name(xfs_attr_leafblock_t *leafp, int idx)
+{
+ struct xfs_attr_leaf_entry *entries = xfs_attr3_leaf_entryp(leafp);
+
+ return &((char *)leafp)[be16_to_cpu(entries[idx].nameidx)];
+}
+
+static inline xfs_attr_leaf_name_remote_t *
+xfs_attr3_leaf_name_remote(xfs_attr_leafblock_t *leafp, int idx)
+{
+ return (xfs_attr_leaf_name_remote_t *)xfs_attr3_leaf_name(leafp, idx);
+}
+
+static inline xfs_attr_leaf_name_local_t *
+xfs_attr3_leaf_name_local(xfs_attr_leafblock_t *leafp, int idx)
+{
+ return (xfs_attr_leaf_name_local_t *)xfs_attr3_leaf_name(leafp, idx);
+}
+
+/*
+ * Calculate total bytes used (including trailing pad for alignment) for
+ * a "local" name/value structure, a "remote" name/value structure, and
+ * a pointer which might be either.
+ */
+static inline int xfs_attr_leaf_entsize_remote(int nlen)
+{
+ return ((uint)sizeof(xfs_attr_leaf_name_remote_t) - 1 + (nlen) + \
+ XFS_ATTR_LEAF_NAME_ALIGN - 1) & ~(XFS_ATTR_LEAF_NAME_ALIGN - 1);
+}
+
+static inline int xfs_attr_leaf_entsize_local(int nlen, int vlen)
+{
+ return ((uint)sizeof(xfs_attr_leaf_name_local_t) - 1 + (nlen) + (vlen) +
+ XFS_ATTR_LEAF_NAME_ALIGN - 1) & ~(XFS_ATTR_LEAF_NAME_ALIGN - 1);
+}
+
+static inline int xfs_attr_leaf_entsize_local_max(int bsize)
+{
+ return (((bsize) >> 1) + ((bsize) >> 2));
+}
+
+
+
+/*
+ * Remote attribute block format definition
+ *
+ * There is one of these headers per filesystem block in a remote attribute.
+ * This is done to ensure there is a 1:1 mapping between the attribute value
+ * length and the number of blocks needed to store the attribute. This makes the
+ * verification of a buffer a little more complex, but greatly simplifies the
+ * allocation, reading and writing of these attributes as we don't have to guess
+ * the number of blocks needed to store the attribute data.
+ */
+#define XFS_ATTR3_RMT_MAGIC 0x5841524d /* XARM */
+
+struct xfs_attr3_rmt_hdr {
+ __be32 rm_magic;
+ __be32 rm_offset;
+ __be32 rm_bytes;
+ __be32 rm_crc;
+ uuid_t rm_uuid;
+ __be64 rm_owner;
+ __be64 rm_blkno;
+ __be64 rm_lsn;
+};
+
+#define XFS_ATTR3_RMT_CRC_OFF offsetof(struct xfs_attr3_rmt_hdr, rm_crc)
+
+#define XFS_ATTR3_RMT_BUF_SPACE(mp, bufsize) \
+ ((bufsize) - (xfs_sb_version_hascrc(&(mp)->m_sb) ? \
+ sizeof(struct xfs_attr3_rmt_hdr) : 0))
+
+#endif /* __XFS_DA_FORMAT_H__ */
diff --git a/include/xfs_dir2_format.h b/include/xfs_dir2_format.h
deleted file mode 100644
index 9cf6738..0000000
--- a/include/xfs_dir2_format.h
+++ /dev/null
@@ -1,964 +0,0 @@
-/*
- * Copyright (c) 2000-2001,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
- */
-#ifndef __XFS_DIR2_FORMAT_H__
-#define __XFS_DIR2_FORMAT_H__
-
-/*
- * Directory version 2.
- *
- * There are 4 possible formats:
- * - shortform - embedded into the inode
- * - single block - data with embedded leaf at the end
- * - multiple data blocks, single leaf+freeindex block
- * - data blocks, node and leaf blocks (btree), freeindex blocks
- *
- * Note: many node blocks structures and constants are shared with the attr
- * code and defined in xfs_da_btree.h.
- */
-
-#define XFS_DIR2_BLOCK_MAGIC 0x58443242 /* XD2B: single block dirs */
-#define XFS_DIR2_DATA_MAGIC 0x58443244 /* XD2D: multiblock dirs */
-#define XFS_DIR2_FREE_MAGIC 0x58443246 /* XD2F: free index blocks */
-
-/*
- * Directory Version 3 With CRCs.
- *
- * The tree formats are the same as for version 2 directories. The difference
- * is in the block header and dirent formats. In many cases the v3 structures
- * use v2 definitions as they are no different and this makes code sharing much
- * easier.
- *
- * Also, the xfs_dir3_*() functions handle both v2 and v3 formats - if the
- * format is v2 then they switch to the existing v2 code, or the format is v3
- * they implement the v3 functionality. This means the existing dir2 is a mix of
- * xfs_dir2/xfs_dir3 calls and functions. The xfs_dir3 functions are called
- * where there is a difference in the formats, otherwise the code is unchanged.
- *
- * Where it is possible, the code decides what to do based on the magic numbers
- * in the blocks rather than feature bits in the superblock. This means the code
- * is as independent of the external XFS code as possible as doesn't require
- * passing struct xfs_mount pointers into places where it isn't really
- * necessary.
- *
- * Version 3 includes:
- *
- * - a larger block header for CRC and identification purposes and so the
- * offsets of all the structures inside the blocks are different.
- *
- * - new magic numbers to be able to detect the v2/v3 types on the fly.
- */
-
-#define XFS_DIR3_BLOCK_MAGIC 0x58444233 /* XDB3: single block dirs */
-#define XFS_DIR3_DATA_MAGIC 0x58444433 /* XDD3: multiblock dirs */
-#define XFS_DIR3_FREE_MAGIC 0x58444633 /* XDF3: free index blocks */
-
-/*
- * Dirents in version 3 directories have a file type field. Additions to this
- * list are an on-disk format change, requiring feature bits. Valid values
- * are as follows:
- */
-#define XFS_DIR3_FT_UNKNOWN 0
-#define XFS_DIR3_FT_REG_FILE 1
-#define XFS_DIR3_FT_DIR 2
-#define XFS_DIR3_FT_CHRDEV 3
-#define XFS_DIR3_FT_BLKDEV 4
-#define XFS_DIR3_FT_FIFO 5
-#define XFS_DIR3_FT_SOCK 6
-#define XFS_DIR3_FT_SYMLINK 7
-#define XFS_DIR3_FT_WHT 8
-
-#define XFS_DIR3_FT_MAX 9
-
-/*
- * Byte offset in data block and shortform entry.
- */
-typedef __uint16_t xfs_dir2_data_off_t;
-#define NULLDATAOFF 0xffffU
-typedef uint xfs_dir2_data_aoff_t; /* argument form */
-
-/*
- * Normalized offset (in a data block) of the entry, really xfs_dir2_data_off_t.
- * Only need 16 bits, this is the byte offset into the single block form.
- */
-typedef struct { __uint8_t i[2]; } __arch_pack xfs_dir2_sf_off_t;
-
-/*
- * Offset in data space of a data entry.
- */
-typedef __uint32_t xfs_dir2_dataptr_t;
-#define XFS_DIR2_MAX_DATAPTR ((xfs_dir2_dataptr_t)0xffffffff)
-#define XFS_DIR2_NULL_DATAPTR ((xfs_dir2_dataptr_t)0)
-
-/*
- * Byte offset in a directory.
- */
-typedef xfs_off_t xfs_dir2_off_t;
-
-/*
- * Directory block number (logical dirblk in file)
- */
-typedef __uint32_t xfs_dir2_db_t;
-
-/*
- * Inode number stored as 8 8-bit values.
- */
-typedef struct { __uint8_t i[8]; } xfs_dir2_ino8_t;
-
-/*
- * Inode number stored as 4 8-bit values.
- * Works a lot of the time, when all the inode numbers in a directory
- * fit in 32 bits.
- */
-typedef struct { __uint8_t i[4]; } xfs_dir2_ino4_t;
-
-typedef union {
- xfs_dir2_ino8_t i8;
- xfs_dir2_ino4_t i4;
-} xfs_dir2_inou_t;
-#define XFS_DIR2_MAX_SHORT_INUM ((xfs_ino_t)0xffffffffULL)
-
-/*
- * Directory layout when stored internal to an inode.
- *
- * Small directories are packed as tightly as possible so as to fit into the
- * literal area of the inode. These "shortform" directories consist of a
- * single xfs_dir2_sf_hdr header followed by zero or more xfs_dir2_sf_entry
- * structures. Due the different inode number storage size and the variable
- * length name field in the xfs_dir2_sf_entry all these structure are
- * variable length, and the accessors in this file should be used to iterate
- * over them.
- */
-typedef struct xfs_dir2_sf_hdr {
- __uint8_t count; /* count of entries */
- __uint8_t i8count; /* count of 8-byte inode #s */
- xfs_dir2_inou_t parent; /* parent dir inode number */
-} __arch_pack xfs_dir2_sf_hdr_t;
-
-typedef struct xfs_dir2_sf_entry {
- __u8 namelen; /* actual name length */
- xfs_dir2_sf_off_t offset; /* saved offset */
- __u8 name[]; /* name, variable size */
- /*
- * A single byte containing the file type field follows the inode
- * number for version 3 directory entries.
- *
- * A xfs_dir2_ino8_t or xfs_dir2_ino4_t follows here, at a
- * variable offset after the name.
- */
-} __arch_pack xfs_dir2_sf_entry_t;
-
-static inline int xfs_dir2_sf_hdr_size(int i8count)
-{
- return sizeof(struct xfs_dir2_sf_hdr) -
- (i8count == 0) *
- (sizeof(xfs_dir2_ino8_t) - sizeof(xfs_dir2_ino4_t));
-}
-
-static inline xfs_dir2_data_aoff_t
-xfs_dir2_sf_get_offset(xfs_dir2_sf_entry_t *sfep)
-{
- return get_unaligned_be16(&sfep->offset.i);
-}
-
-static inline void
-xfs_dir2_sf_put_offset(xfs_dir2_sf_entry_t *sfep, xfs_dir2_data_aoff_t off)
-{
- put_unaligned_be16(off, &sfep->offset.i);
-}
-
-static inline struct xfs_dir2_sf_entry *
-xfs_dir2_sf_firstentry(struct xfs_dir2_sf_hdr *hdr)
-{
- return (struct xfs_dir2_sf_entry *)
- ((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
- * offset after the inode number. Because it's only a single byte, endian
- * conversion is not necessary.
- */
-static inline __uint8_t *
-xfs_dir3_sfe_ftypep(
- struct xfs_dir2_sf_hdr *hdr,
- struct xfs_dir2_sf_entry *sfep)
-{
- return (__uint8_t *)&sfep->name[sfep->namelen];
-}
-
-static inline __uint8_t
-xfs_dir3_sfe_get_ftype(
- struct xfs_mount *mp,
- struct xfs_dir2_sf_hdr *hdr,
- struct xfs_dir2_sf_entry *sfep)
-{
- __uint8_t *ftp;
-
- if (!xfs_sb_version_hasftype(&mp->m_sb))
- return XFS_DIR3_FT_UNKNOWN;
-
- ftp = xfs_dir3_sfe_ftypep(hdr, sfep);
- if (*ftp >= XFS_DIR3_FT_MAX)
- return XFS_DIR3_FT_UNKNOWN;
- return *ftp;
-}
-
-static inline void
-xfs_dir3_sfe_put_ftype(
- struct xfs_mount *mp,
- struct xfs_dir2_sf_hdr *hdr,
- struct xfs_dir2_sf_entry *sfep,
- __uint8_t ftype)
-{
- __uint8_t *ftp;
-
- ASSERT(ftype < XFS_DIR3_FT_MAX);
-
- if (!xfs_sb_version_hasftype(&mp->m_sb))
- return;
- ftp = xfs_dir3_sfe_ftypep(hdr, sfep);
- *ftp = ftype;
-}
-
-/*
- * Data block structures.
- *
- * A pure data block looks like the following drawing on disk:
- *
- * +-------------------------------------------------+
- * | xfs_dir2_data_hdr_t |
- * +-------------------------------------------------+
- * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t |
- * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t |
- * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t |
- * | ... |
- * +-------------------------------------------------+
- * | unused space |
- * +-------------------------------------------------+
- *
- * As all the entries are variable size structures the accessors below should
- * be used to iterate over them.
- *
- * In addition to the pure data blocks for the data and node formats,
- * most structures are also used for the combined data/freespace "block"
- * format below.
- */
-
-#define XFS_DIR2_DATA_ALIGN_LOG 3 /* i.e., 8 bytes */
-#define XFS_DIR2_DATA_ALIGN (1 << XFS_DIR2_DATA_ALIGN_LOG)
-#define XFS_DIR2_DATA_FREE_TAG 0xffff
-#define XFS_DIR2_DATA_FD_COUNT 3
-
-/*
- * Directory address space divided into sections,
- * spaces separated by 32GB.
- */
-#define XFS_DIR2_SPACE_SIZE (1ULL << (32 + XFS_DIR2_DATA_ALIGN_LOG))
-#define XFS_DIR2_DATA_SPACE 0
-#define XFS_DIR2_DATA_OFFSET (XFS_DIR2_DATA_SPACE * XFS_DIR2_SPACE_SIZE)
-#define XFS_DIR2_DATA_FIRSTDB(mp) \
- xfs_dir2_byte_to_db(mp, XFS_DIR2_DATA_OFFSET)
-
-/*
- * Describe a free area in the data block.
- *
- * The freespace will be formatted as a xfs_dir2_data_unused_t.
- */
-typedef struct xfs_dir2_data_free {
- __be16 offset; /* start of freespace */
- __be16 length; /* length of freespace */
-} xfs_dir2_data_free_t;
-
-/*
- * Header for the data blocks.
- *
- * The code knows that XFS_DIR2_DATA_FD_COUNT is 3.
- */
-typedef struct xfs_dir2_data_hdr {
- __be32 magic; /* XFS_DIR2_DATA_MAGIC or */
- /* XFS_DIR2_BLOCK_MAGIC */
- xfs_dir2_data_free_t bestfree[XFS_DIR2_DATA_FD_COUNT];
-} xfs_dir2_data_hdr_t;
-
-/*
- * define a structure for all the verification fields we are adding to the
- * directory block structures. This will be used in several structures.
- * The magic number must be the first entry to align with all the dir2
- * structures so we determine how to decode them just by the magic number.
- */
-struct xfs_dir3_blk_hdr {
- __be32 magic; /* magic number */
- __be32 crc; /* CRC of block */
- __be64 blkno; /* first block of the buffer */
- __be64 lsn; /* sequence number of last write */
- uuid_t uuid; /* filesystem we belong to */
- __be64 owner; /* inode that owns the block */
-};
-
-struct xfs_dir3_data_hdr {
- struct xfs_dir3_blk_hdr hdr;
- xfs_dir2_data_free_t best_free[XFS_DIR2_DATA_FD_COUNT];
- __be32 pad; /* 64 bit alignment */
-};
-
-#define XFS_DIR3_DATA_CRC_OFF offsetof(struct xfs_dir3_data_hdr, hdr.crc)
-
-static inline struct xfs_dir2_data_free *
-xfs_dir3_data_bestfree_p(struct xfs_dir2_data_hdr *hdr)
-{
- if (hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
- hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) {
- struct xfs_dir3_data_hdr *hdr3 = (struct xfs_dir3_data_hdr *)hdr;
- return hdr3->best_free;
- }
- return hdr->bestfree;
-}
-
-/*
- * Active entry in a data block.
- *
- * Aligned to 8 bytes. After the variable length name field there is a
- * 2 byte tag field, which can be accessed using xfs_dir3_data_entry_tag_p.
- *
- * For dir3 structures, there is file type field between the name and the tag.
- * This can only be manipulated by helper functions. It is packed hard against
- * the end of the name so any padding for rounding is between the file type and
- * the tag.
- */
-typedef struct xfs_dir2_data_entry {
- __be64 inumber; /* inode number */
- __u8 namelen; /* name length */
- __u8 name[]; /* name bytes, no null */
- /* __u8 filetype; */ /* type of inode we point to */
- /* __be16 tag; */ /* starting offset of us */
-} xfs_dir2_data_entry_t;
-
-/*
- * Unused entry in a data block.
- *
- * Aligned to 8 bytes. Tag appears as the last 2 bytes and must be accessed
- * using xfs_dir2_data_unused_tag_p.
- */
-typedef struct xfs_dir2_data_unused {
- __be16 freetag; /* XFS_DIR2_DATA_FREE_TAG */
- __be16 length; /* total free length */
- /* variable offset */
- __be16 tag; /* starting offset of us */
-} xfs_dir2_data_unused_t;
-
-/*
- * Size of a data entry.
- */
-static inline 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 inline int
-xfs_dir3_data_entsize(
- struct xfs_mount *mp,
- int n)
-{
- bool ftype = xfs_sb_version_hasftype(&mp->m_sb) ? true : false;
- return __xfs_dir3_data_entsize(ftype, n);
-}
-
-static inline __uint8_t
-xfs_dir3_dirent_get_ftype(
- struct xfs_mount *mp,
- struct xfs_dir2_data_entry *dep)
-{
- if (xfs_sb_version_hasftype(&mp->m_sb)) {
- __uint8_t type = dep->name[dep->namelen];
-
- ASSERT(type < XFS_DIR3_FT_MAX);
- if (type < XFS_DIR3_FT_MAX)
- return type;
-
- }
- return XFS_DIR3_FT_UNKNOWN;
-}
-
-static inline void
-xfs_dir3_dirent_put_ftype(
- struct xfs_mount *mp,
- struct xfs_dir2_data_entry *dep,
- __uint8_t type)
-{
- ASSERT(type < XFS_DIR3_FT_MAX);
- ASSERT(dep->namelen != 0);
-
- if (xfs_sb_version_hasftype(&mp->m_sb))
- dep->name[dep->namelen] = type;
-}
-
-/*
- * Pointer to an entry's tag word.
- */
-static inline __be16 *
-xfs_dir3_data_entry_tag_p(
- struct xfs_mount *mp,
- struct xfs_dir2_data_entry *dep)
-{
- return (__be16 *)((char *)dep +
- xfs_dir3_data_entsize(mp, dep->namelen) - sizeof(__be16));
-}
-
-/*
- * Pointer to a freespace's tag word.
- */
-static inline __be16 *
-xfs_dir2_data_unused_tag_p(struct xfs_dir2_data_unused *dup)
-{
- return (__be16 *)((char *)dup +
- be16_to_cpu(dup->length) - sizeof(__be16));
-}
-
-static inline size_t
-xfs_dir3_data_hdr_size(bool dir3)
-{
- if (dir3)
- return sizeof(struct xfs_dir3_data_hdr);
- return sizeof(struct xfs_dir2_data_hdr);
-}
-
-static inline size_t
-xfs_dir3_data_entry_offset(struct xfs_dir2_data_hdr *hdr)
-{
- bool dir3 = hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
- hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC);
- return xfs_dir3_data_hdr_size(dir3);
-}
-
-static inline 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(hdr));
-}
-
-static inline 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(hdr));
-}
-
-/*
- * Offsets of . and .. in data space (always block 0)
- *
- * XXX: there is scope for significant optimisation of the logic here. Right
- * now we are checking for "dir3 format" over and over again. Ideally we should
- * only do it once for each operation.
- */
-static inline xfs_dir2_data_aoff_t
-xfs_dir3_data_dot_offset(struct xfs_mount *mp)
-{
- return xfs_dir3_data_hdr_size(xfs_sb_version_hascrc(&mp->m_sb));
-}
-
-static inline xfs_dir2_data_aoff_t
-xfs_dir3_data_dotdot_offset(struct xfs_mount *mp)
-{
- return xfs_dir3_data_dot_offset(mp) +
- xfs_dir3_data_entsize(mp, 1);
-}
-
-static inline xfs_dir2_data_aoff_t
-xfs_dir3_data_first_offset(struct xfs_mount *mp)
-{
- return xfs_dir3_data_dotdot_offset(mp) +
- xfs_dir3_data_entsize(mp, 2);
-}
-
-/*
- * location of . and .. in data space (always block 0)
- */
-static inline struct xfs_dir2_data_entry *
-xfs_dir3_data_dot_entry_p(
- struct xfs_mount *mp,
- struct xfs_dir2_data_hdr *hdr)
-{
- return (struct xfs_dir2_data_entry *)
- ((char *)hdr + xfs_dir3_data_dot_offset(mp));
-}
-
-static inline struct xfs_dir2_data_entry *
-xfs_dir3_data_dotdot_entry_p(
- struct xfs_mount *mp,
- struct xfs_dir2_data_hdr *hdr)
-{
- return (struct xfs_dir2_data_entry *)
- ((char *)hdr + xfs_dir3_data_dotdot_offset(mp));
-}
-
-static inline struct xfs_dir2_data_entry *
-xfs_dir3_data_first_entry_p(
- struct xfs_mount *mp,
- struct xfs_dir2_data_hdr *hdr)
-{
- return (struct xfs_dir2_data_entry *)
- ((char *)hdr + xfs_dir3_data_first_offset(mp));
-}
-
-/*
- * Leaf block structures.
- *
- * A pure leaf block looks like the following drawing on disk:
- *
- * +---------------------------+
- * | xfs_dir2_leaf_hdr_t |
- * +---------------------------+
- * | xfs_dir2_leaf_entry_t |
- * | xfs_dir2_leaf_entry_t |
- * | xfs_dir2_leaf_entry_t |
- * | xfs_dir2_leaf_entry_t |
- * | ... |
- * +---------------------------+
- * | xfs_dir2_data_off_t |
- * | xfs_dir2_data_off_t |
- * | xfs_dir2_data_off_t |
- * | ... |
- * +---------------------------+
- * | xfs_dir2_leaf_tail_t |
- * +---------------------------+
- *
- * The xfs_dir2_data_off_t members (bests) and tail are at the end of the block
- * for single-leaf (magic = XFS_DIR2_LEAF1_MAGIC) blocks only, but not present
- * for directories with separate leaf nodes and free space blocks
- * (magic = XFS_DIR2_LEAFN_MAGIC).
- *
- * As all the entries are variable size structures the accessors below should
- * be used to iterate over them.
- */
-
-/*
- * Offset of the leaf/node space. First block in this space
- * is the btree root.
- */
-#define XFS_DIR2_LEAF_SPACE 1
-#define XFS_DIR2_LEAF_OFFSET (XFS_DIR2_LEAF_SPACE * XFS_DIR2_SPACE_SIZE)
-#define XFS_DIR2_LEAF_FIRSTDB(mp) \
- xfs_dir2_byte_to_db(mp, XFS_DIR2_LEAF_OFFSET)
-
-/*
- * Leaf block header.
- */
-typedef struct xfs_dir2_leaf_hdr {
- xfs_da_blkinfo_t info; /* header for da routines */
- __be16 count; /* count of entries */
- __be16 stale; /* count of stale entries */
-} xfs_dir2_leaf_hdr_t;
-
-struct xfs_dir3_leaf_hdr {
- struct xfs_da3_blkinfo info; /* header for da routines */
- __be16 count; /* count of entries */
- __be16 stale; /* count of stale entries */
- __be32 pad; /* 64 bit alignment */
-};
-
-struct xfs_dir3_icleaf_hdr {
- __uint32_t forw;
- __uint32_t back;
- __uint16_t magic;
- __uint16_t count;
- __uint16_t stale;
-};
-
-/*
- * Leaf block entry.
- */
-typedef struct xfs_dir2_leaf_entry {
- __be32 hashval; /* hash value of name */
- __be32 address; /* address of data entry */
-} xfs_dir2_leaf_entry_t;
-
-/*
- * Leaf block tail.
- */
-typedef struct xfs_dir2_leaf_tail {
- __be32 bestcount;
-} xfs_dir2_leaf_tail_t;
-
-/*
- * Leaf block.
- */
-typedef struct xfs_dir2_leaf {
- xfs_dir2_leaf_hdr_t hdr; /* leaf header */
- xfs_dir2_leaf_entry_t __ents[]; /* entries */
-} xfs_dir2_leaf_t;
-
-struct xfs_dir3_leaf {
- struct xfs_dir3_leaf_hdr hdr; /* leaf header */
- struct xfs_dir2_leaf_entry __ents[]; /* entries */
-};
-
-#define XFS_DIR3_LEAF_CRC_OFF offsetof(struct xfs_dir3_leaf_hdr, info.crc)
-
-extern void xfs_dir3_leaf_hdr_from_disk(struct xfs_dir3_icleaf_hdr *to,
- struct xfs_dir2_leaf *from);
-
-static inline int
-xfs_dir3_leaf_hdr_size(struct xfs_dir2_leaf *lp)
-{
- if (lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) ||
- lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC))
- return sizeof(struct xfs_dir3_leaf_hdr);
- return sizeof(struct xfs_dir2_leaf_hdr);
-}
-
-static inline int
-xfs_dir3_max_leaf_ents(struct xfs_mount *mp, struct xfs_dir2_leaf *lp)
-{
- return (mp->m_dirblksize - xfs_dir3_leaf_hdr_size(lp)) /
- (uint)sizeof(struct xfs_dir2_leaf_entry);
-}
-
-/*
- * Get address of the bestcount field in the single-leaf block.
- */
-static inline struct xfs_dir2_leaf_entry *
-xfs_dir3_leaf_ents_p(struct xfs_dir2_leaf *lp)
-{
- if (lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) ||
- lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)) {
- struct xfs_dir3_leaf *lp3 = (struct xfs_dir3_leaf *)lp;
- return lp3->__ents;
- }
- return lp->__ents;
-}
-
-/*
- * Get address of the bestcount field in the single-leaf block.
- */
-static inline struct xfs_dir2_leaf_tail *
-xfs_dir2_leaf_tail_p(struct xfs_mount *mp, struct xfs_dir2_leaf *lp)
-{
- return (struct xfs_dir2_leaf_tail *)
- ((char *)lp + mp->m_dirblksize -
- sizeof(struct xfs_dir2_leaf_tail));
-}
-
-/*
- * Get address of the bests array in the single-leaf block.
- */
-static inline __be16 *
-xfs_dir2_leaf_bests_p(struct xfs_dir2_leaf_tail *ltp)
-{
- return (__be16 *)ltp - be32_to_cpu(ltp->bestcount);
-}
-
-/*
- * DB blocks here are logical directory block numbers, not filesystem blocks.
- */
-
-/*
- * Convert dataptr to byte in file space
- */
-static inline xfs_dir2_off_t
-xfs_dir2_dataptr_to_byte(struct xfs_mount *mp, xfs_dir2_dataptr_t dp)
-{
- return (xfs_dir2_off_t)dp << XFS_DIR2_DATA_ALIGN_LOG;
-}
-
-/*
- * Convert byte in file space to dataptr. It had better be aligned.
- */
-static inline xfs_dir2_dataptr_t
-xfs_dir2_byte_to_dataptr(struct xfs_mount *mp, xfs_dir2_off_t by)
-{
- return (xfs_dir2_dataptr_t)(by >> XFS_DIR2_DATA_ALIGN_LOG);
-}
-
-/*
- * Convert byte in space to (DB) block
- */
-static inline xfs_dir2_db_t
-xfs_dir2_byte_to_db(struct xfs_mount *mp, xfs_dir2_off_t by)
-{
- return (xfs_dir2_db_t)
- (by >> (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog));
-}
-
-/*
- * Convert dataptr to a block number
- */
-static inline xfs_dir2_db_t
-xfs_dir2_dataptr_to_db(struct xfs_mount *mp, xfs_dir2_dataptr_t dp)
-{
- return xfs_dir2_byte_to_db(mp, xfs_dir2_dataptr_to_byte(mp, dp));
-}
-
-/*
- * Convert byte in space to offset in a block
- */
-static inline xfs_dir2_data_aoff_t
-xfs_dir2_byte_to_off(struct xfs_mount *mp, xfs_dir2_off_t by)
-{
- return (xfs_dir2_data_aoff_t)(by &
- ((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) - 1));
-}
-
-/*
- * Convert dataptr to a byte offset in a block
- */
-static inline xfs_dir2_data_aoff_t
-xfs_dir2_dataptr_to_off(struct xfs_mount *mp, xfs_dir2_dataptr_t dp)
-{
- return xfs_dir2_byte_to_off(mp, xfs_dir2_dataptr_to_byte(mp, dp));
-}
-
-/*
- * Convert block and offset to byte in space
- */
-static inline xfs_dir2_off_t
-xfs_dir2_db_off_to_byte(struct xfs_mount *mp, xfs_dir2_db_t db,
- xfs_dir2_data_aoff_t o)
-{
- return ((xfs_dir2_off_t)db <<
- (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) + o;
-}
-
-/*
- * Convert block (DB) to block (dablk)
- */
-static inline xfs_dablk_t
-xfs_dir2_db_to_da(struct xfs_mount *mp, xfs_dir2_db_t db)
-{
- return (xfs_dablk_t)(db << mp->m_sb.sb_dirblklog);
-}
-
-/*
- * Convert byte in space to (DA) block
- */
-static inline xfs_dablk_t
-xfs_dir2_byte_to_da(struct xfs_mount *mp, xfs_dir2_off_t by)
-{
- return xfs_dir2_db_to_da(mp, xfs_dir2_byte_to_db(mp, by));
-}
-
-/*
- * Convert block and offset to dataptr
- */
-static inline xfs_dir2_dataptr_t
-xfs_dir2_db_off_to_dataptr(struct xfs_mount *mp, xfs_dir2_db_t db,
- xfs_dir2_data_aoff_t o)
-{
- return xfs_dir2_byte_to_dataptr(mp, xfs_dir2_db_off_to_byte(mp, db, o));
-}
-
-/*
- * Convert block (dablk) to block (DB)
- */
-static inline xfs_dir2_db_t
-xfs_dir2_da_to_db(struct xfs_mount *mp, xfs_dablk_t da)
-{
- return (xfs_dir2_db_t)(da >> mp->m_sb.sb_dirblklog);
-}
-
-/*
- * Convert block (dablk) to byte offset in space
- */
-static inline xfs_dir2_off_t
-xfs_dir2_da_to_byte(struct xfs_mount *mp, xfs_dablk_t da)
-{
- return xfs_dir2_db_off_to_byte(mp, xfs_dir2_da_to_db(mp, da), 0);
-}
-
-/*
- * Free space block defintions for the node format.
- */
-
-/*
- * Offset of the freespace index.
- */
-#define XFS_DIR2_FREE_SPACE 2
-#define XFS_DIR2_FREE_OFFSET (XFS_DIR2_FREE_SPACE * XFS_DIR2_SPACE_SIZE)
-#define XFS_DIR2_FREE_FIRSTDB(mp) \
- xfs_dir2_byte_to_db(mp, XFS_DIR2_FREE_OFFSET)
-
-typedef struct xfs_dir2_free_hdr {
- __be32 magic; /* XFS_DIR2_FREE_MAGIC */
- __be32 firstdb; /* db of first entry */
- __be32 nvalid; /* count of valid entries */
- __be32 nused; /* count of used entries */
-} xfs_dir2_free_hdr_t;
-
-typedef struct xfs_dir2_free {
- xfs_dir2_free_hdr_t hdr; /* block header */
- __be16 bests[]; /* best free counts */
- /* unused entries are -1 */
-} xfs_dir2_free_t;
-
-struct xfs_dir3_free_hdr {
- struct xfs_dir3_blk_hdr hdr;
- __be32 firstdb; /* db of first entry */
- __be32 nvalid; /* count of valid entries */
- __be32 nused; /* count of used entries */
- __be32 pad; /* 64 bit alignment */
-};
-
-struct xfs_dir3_free {
- struct xfs_dir3_free_hdr hdr;
- __be16 bests[]; /* best free counts */
- /* unused entries are -1 */
-};
-
-#define XFS_DIR3_FREE_CRC_OFF offsetof(struct xfs_dir3_free, hdr.hdr.crc)
-
-/*
- * In core version of the free block header, abstracted away from on-disk format
- * differences. Use this in the code, and convert to/from the disk version using
- * xfs_dir3_free_hdr_from_disk/xfs_dir3_free_hdr_to_disk.
- */
-struct xfs_dir3_icfree_hdr {
- __uint32_t magic;
- __uint32_t firstdb;
- __uint32_t nvalid;
- __uint32_t nused;
-
-};
-
-void xfs_dir3_free_hdr_from_disk(struct xfs_dir3_icfree_hdr *to,
- struct xfs_dir2_free *from);
-
-static inline int
-xfs_dir3_free_hdr_size(struct xfs_mount *mp)
-{
- if (xfs_sb_version_hascrc(&mp->m_sb))
- return sizeof(struct xfs_dir3_free_hdr);
- return sizeof(struct xfs_dir2_free_hdr);
-}
-
-static inline int
-xfs_dir3_free_max_bests(struct xfs_mount *mp)
-{
- return (mp->m_dirblksize - xfs_dir3_free_hdr_size(mp)) /
- sizeof(xfs_dir2_data_off_t);
-}
-
-static inline __be16 *
-xfs_dir3_free_bests_p(struct xfs_mount *mp, struct xfs_dir2_free *free)
-{
- return (__be16 *)((char *)free + xfs_dir3_free_hdr_size(mp));
-}
-
-/*
- * Convert data space db to the corresponding free db.
- */
-static inline xfs_dir2_db_t
-xfs_dir2_db_to_fdb(struct xfs_mount *mp, xfs_dir2_db_t db)
-{
- return XFS_DIR2_FREE_FIRSTDB(mp) + db / xfs_dir3_free_max_bests(mp);
-}
-
-/*
- * Convert data space db to the corresponding index in a free db.
- */
-static inline int
-xfs_dir2_db_to_fdindex(struct xfs_mount *mp, xfs_dir2_db_t db)
-{
- return db % xfs_dir3_free_max_bests(mp);
-}
-
-/*
- * Single block format.
- *
- * The single block format looks like the following drawing on disk:
- *
- * +-------------------------------------------------+
- * | xfs_dir2_data_hdr_t |
- * +-------------------------------------------------+
- * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t |
- * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t |
- * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t :
- * | ... |
- * +-------------------------------------------------+
- * | unused space |
- * +-------------------------------------------------+
- * | ... |
- * | xfs_dir2_leaf_entry_t |
- * | xfs_dir2_leaf_entry_t |
- * +-------------------------------------------------+
- * | xfs_dir2_block_tail_t |
- * +-------------------------------------------------+
- *
- * As all the entries are variable size structures the accessors below should
- * be used to iterate over them.
- */
-
-typedef struct xfs_dir2_block_tail {
- __be32 count; /* count of leaf entries */
- __be32 stale; /* count of stale lf entries */
-} xfs_dir2_block_tail_t;
-
-/*
- * Pointer to the leaf header embedded in a data block (1-block format)
- */
-static inline struct xfs_dir2_block_tail *
-xfs_dir2_block_tail_p(struct xfs_mount *mp, struct xfs_dir2_data_hdr *hdr)
-{
- return ((struct xfs_dir2_block_tail *)
- ((char *)hdr + mp->m_dirblksize)) - 1;
-}
-
-/*
- * Pointer to the leaf entries embedded in a data block (1-block format)
- */
-static inline struct xfs_dir2_leaf_entry *
-xfs_dir2_block_leaf_p(struct xfs_dir2_block_tail *btp)
-{
- return ((struct xfs_dir2_leaf_entry *)btp) - be32_to_cpu(btp->count);
-}
-
-#endif /* __XFS_DIR2_FORMAT_H__ */
--
1.8.3.2
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 10/32] xfs: split dquot buffer operations out
[not found] <1380510944-8571-1-git-send-email-david@fromorbit.com>
` (8 preceding siblings ...)
2013-09-30 3:15 ` [PATCH 09/32] xfs: unify directory/attribute format definitions Dave Chinner
@ 2013-09-30 3:15 ` Dave Chinner
2013-09-30 3:15 ` [PATCH 11/32] xfs: decouple inode and bmap btree header files Dave Chinner
` (21 subsequent siblings)
31 siblings, 0 replies; 56+ messages in thread
From: Dave Chinner @ 2013-09-30 3:15 UTC (permalink / raw)
To: xfs
From: Dave Chinner <dchinner@redhat.com>
Parts of userspace want to be able to read and modify dquot buffers
(e.g. xfs_db) so we need to split out the reading and writing of
these buffers so it is easy to shared code with libxfs in userspace.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
include/libxfs.h | 9 ++
libxfs/Makefile | 1 +
libxfs/xfs_dquot_buf.c | 273 +++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 283 insertions(+)
create mode 100644 libxfs/xfs_dquot_buf.c
diff --git a/include/libxfs.h b/include/libxfs.h
index 835ba37..f10ab59 100644
--- a/include/libxfs.h
+++ b/include/libxfs.h
@@ -216,6 +216,15 @@ typedef struct xfs_mount {
xfs_dablk_t m_dirdatablk; /* blockno of dir data v2 */
xfs_dablk_t m_dirleafblk; /* blockno of dir non-data v2 */
xfs_dablk_t m_dirfreeblk; /* blockno of dirfreeindex v2 */
+
+ /*
+ * anonymous struct to allow xfs_dquot_buf.c to compile.
+ * Pointer is always null in userspace, so code does not use it at all
+ */
+ struct {
+ int qi_dqperchunk;
+ } *m_quotainfo;
+
} xfs_mount_t;
/*
diff --git a/libxfs/Makefile b/libxfs/Makefile
index f0cbae3..4522218 100644
--- a/libxfs/Makefile
+++ b/libxfs/Makefile
@@ -29,6 +29,7 @@ CFILES = cache.c \
xfs_dir2_leaf.c \
xfs_dir2_node.c \
xfs_dir2_sf.c \
+ xfs_dquot_buf.c \
xfs_ialloc.c \
xfs_inode_buf.c \
xfs_inode_fork.c \
diff --git a/libxfs/xfs_dquot_buf.c b/libxfs/xfs_dquot_buf.c
new file mode 100644
index 0000000..620d9d3
--- /dev/null
+++ b/libxfs/xfs_dquot_buf.c
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2000-2006 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"
+
+int
+xfs_calc_dquots_per_chunk(
+ struct xfs_mount *mp,
+ unsigned int nbblks) /* basic block units */
+{
+ unsigned int ndquots;
+
+ ASSERT(nbblks > 0);
+ ndquots = BBTOB(nbblks);
+ do_div(ndquots, sizeof(xfs_dqblk_t));
+
+ return ndquots;
+}
+
+/*
+ * Do some primitive error checking on ondisk dquot data structures.
+ */
+int
+xfs_dqcheck(
+ struct xfs_mount *mp,
+ xfs_disk_dquot_t *ddq,
+ xfs_dqid_t id,
+ uint type, /* used only when IO_dorepair is true */
+ uint flags,
+ char *str)
+{
+ xfs_dqblk_t *d = (xfs_dqblk_t *)ddq;
+ int errs = 0;
+
+ /*
+ * We can encounter an uninitialized dquot buffer for 2 reasons:
+ * 1. If we crash while deleting the quotainode(s), and those blks got
+ * used for user data. This is because we take the path of regular
+ * file deletion; however, the size field of quotainodes is never
+ * updated, so all the tricks that we play in itruncate_finish
+ * don't quite matter.
+ *
+ * 2. We don't play the quota buffers when there's a quotaoff logitem.
+ * But the allocation will be replayed so we'll end up with an
+ * uninitialized quota block.
+ *
+ * This is all fine; things are still consistent, and we haven't lost
+ * any quota information. Just don't complain about bad dquot blks.
+ */
+ if (ddq->d_magic != cpu_to_be16(XFS_DQUOT_MAGIC)) {
+ if (flags & XFS_QMOPT_DOWARN)
+ xfs_alert(mp,
+ "%s : XFS dquot ID 0x%x, magic 0x%x != 0x%x",
+ str, id, be16_to_cpu(ddq->d_magic), XFS_DQUOT_MAGIC);
+ errs++;
+ }
+ if (ddq->d_version != XFS_DQUOT_VERSION) {
+ if (flags & XFS_QMOPT_DOWARN)
+ xfs_alert(mp,
+ "%s : XFS dquot ID 0x%x, version 0x%x != 0x%x",
+ str, id, ddq->d_version, XFS_DQUOT_VERSION);
+ errs++;
+ }
+
+ if (ddq->d_flags != XFS_DQ_USER &&
+ ddq->d_flags != XFS_DQ_PROJ &&
+ ddq->d_flags != XFS_DQ_GROUP) {
+ if (flags & XFS_QMOPT_DOWARN)
+ xfs_alert(mp,
+ "%s : XFS dquot ID 0x%x, unknown flags 0x%x",
+ str, id, ddq->d_flags);
+ errs++;
+ }
+
+ if (id != -1 && id != be32_to_cpu(ddq->d_id)) {
+ if (flags & XFS_QMOPT_DOWARN)
+ xfs_alert(mp,
+ "%s : ondisk-dquot 0x%p, ID mismatch: "
+ "0x%x expected, found id 0x%x",
+ str, ddq, id, be32_to_cpu(ddq->d_id));
+ errs++;
+ }
+
+ if (!errs && ddq->d_id) {
+ if (ddq->d_blk_softlimit &&
+ be64_to_cpu(ddq->d_bcount) >
+ be64_to_cpu(ddq->d_blk_softlimit)) {
+ if (!ddq->d_btimer) {
+ if (flags & XFS_QMOPT_DOWARN)
+ xfs_alert(mp,
+ "%s : Dquot ID 0x%x (0x%p) BLK TIMER NOT STARTED",
+ str, (int)be32_to_cpu(ddq->d_id), ddq);
+ errs++;
+ }
+ }
+ if (ddq->d_ino_softlimit &&
+ be64_to_cpu(ddq->d_icount) >
+ be64_to_cpu(ddq->d_ino_softlimit)) {
+ if (!ddq->d_itimer) {
+ if (flags & XFS_QMOPT_DOWARN)
+ xfs_alert(mp,
+ "%s : Dquot ID 0x%x (0x%p) INODE TIMER NOT STARTED",
+ str, (int)be32_to_cpu(ddq->d_id), ddq);
+ errs++;
+ }
+ }
+ if (ddq->d_rtb_softlimit &&
+ be64_to_cpu(ddq->d_rtbcount) >
+ be64_to_cpu(ddq->d_rtb_softlimit)) {
+ if (!ddq->d_rtbtimer) {
+ if (flags & XFS_QMOPT_DOWARN)
+ xfs_alert(mp,
+ "%s : Dquot ID 0x%x (0x%p) RTBLK TIMER NOT STARTED",
+ str, (int)be32_to_cpu(ddq->d_id), ddq);
+ errs++;
+ }
+ }
+ }
+
+ if (!errs || !(flags & XFS_QMOPT_DQREPAIR))
+ return errs;
+
+ if (flags & XFS_QMOPT_DOWARN)
+ xfs_notice(mp, "Re-initializing dquot ID 0x%x", id);
+
+ /*
+ * Typically, a repair is only requested by quotacheck.
+ */
+ ASSERT(id != -1);
+ ASSERT(flags & XFS_QMOPT_DQREPAIR);
+ memset(d, 0, sizeof(xfs_dqblk_t));
+
+ d->dd_diskdq.d_magic = cpu_to_be16(XFS_DQUOT_MAGIC);
+ d->dd_diskdq.d_version = XFS_DQUOT_VERSION;
+ d->dd_diskdq.d_flags = type;
+ d->dd_diskdq.d_id = cpu_to_be32(id);
+
+ if (xfs_sb_version_hascrc(&mp->m_sb)) {
+ uuid_copy(&d->dd_uuid, &mp->m_sb.sb_uuid);
+ xfs_update_cksum((char *)d, sizeof(struct xfs_dqblk),
+ XFS_DQUOT_CRC_OFF);
+ }
+
+ return errs;
+}
+
+STATIC bool
+xfs_dquot_buf_verify_crc(
+ struct xfs_mount *mp,
+ struct xfs_buf *bp)
+{
+ struct xfs_dqblk *d = (struct xfs_dqblk *)bp->b_addr;
+ int ndquots;
+ int i;
+
+ if (!xfs_sb_version_hascrc(&mp->m_sb))
+ return true;
+
+ /*
+ * if we are in log recovery, the quota subsystem has not been
+ * initialised so we have no quotainfo structure. In that case, we need
+ * to manually calculate the number of dquots in the buffer.
+ */
+ if (mp->m_quotainfo)
+ ndquots = mp->m_quotainfo->qi_dqperchunk;
+ else
+ ndquots = xfs_calc_dquots_per_chunk(mp,
+ XFS_BB_TO_FSB(mp, bp->b_length));
+
+ for (i = 0; i < ndquots; i++, d++) {
+ if (!xfs_verify_cksum((char *)d, sizeof(struct xfs_dqblk),
+ XFS_DQUOT_CRC_OFF))
+ return false;
+ if (!uuid_equal(&d->dd_uuid, &mp->m_sb.sb_uuid))
+ return false;
+ }
+ return true;
+}
+
+STATIC bool
+xfs_dquot_buf_verify(
+ struct xfs_mount *mp,
+ struct xfs_buf *bp)
+{
+ struct xfs_dqblk *d = (struct xfs_dqblk *)bp->b_addr;
+ xfs_dqid_t id = 0;
+ int ndquots;
+ int i;
+
+ /*
+ * if we are in log recovery, the quota subsystem has not been
+ * initialised so we have no quotainfo structure. In that case, we need
+ * to manually calculate the number of dquots in the buffer.
+ */
+ if (mp->m_quotainfo)
+ ndquots = mp->m_quotainfo->qi_dqperchunk;
+ else
+ ndquots = xfs_calc_dquots_per_chunk(mp, bp->b_length);
+
+ /*
+ * On the first read of the buffer, verify that each dquot is valid.
+ * We don't know what the id of the dquot is supposed to be, just that
+ * they should be increasing monotonically within the buffer. If the
+ * first id is corrupt, then it will fail on the second dquot in the
+ * buffer so corruptions could point to the wrong dquot in this case.
+ */
+ for (i = 0; i < ndquots; i++) {
+ struct xfs_disk_dquot *ddq;
+ int error;
+
+ ddq = &d[i].dd_diskdq;
+
+ if (i == 0)
+ id = be32_to_cpu(ddq->d_id);
+
+ error = xfs_dqcheck(mp, ddq, id + i, 0, XFS_QMOPT_DOWARN,
+ "xfs_dquot_buf_verify");
+ if (error)
+ return false;
+ }
+ return true;
+}
+
+static void
+xfs_dquot_buf_read_verify(
+ struct xfs_buf *bp)
+{
+ struct xfs_mount *mp = bp->b_target->bt_mount;
+
+ if (!xfs_dquot_buf_verify_crc(mp, bp) || !xfs_dquot_buf_verify(mp, bp)) {
+ XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
+ xfs_buf_ioerror(bp, EFSCORRUPTED);
+ }
+}
+
+/*
+ * we don't calculate the CRC here as that is done when the dquot is flushed to
+ * the buffer after the update is done. This ensures that the dquot in the
+ * buffer always has an up-to-date CRC value.
+ */
+void
+xfs_dquot_buf_write_verify(
+ struct xfs_buf *bp)
+{
+ struct xfs_mount *mp = bp->b_target->bt_mount;
+
+ if (!xfs_dquot_buf_verify(mp, bp)) {
+ XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
+ xfs_buf_ioerror(bp, EFSCORRUPTED);
+ return;
+ }
+}
+
+const struct xfs_buf_ops xfs_dquot_buf_ops = {
+ .verify_read = xfs_dquot_buf_read_verify,
+ .verify_write = xfs_dquot_buf_write_verify,
+};
+
--
1.8.3.2
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 11/32] xfs: decouple inode and bmap btree header files
[not found] <1380510944-8571-1-git-send-email-david@fromorbit.com>
` (9 preceding siblings ...)
2013-09-30 3:15 ` [PATCH 10/32] xfs: split dquot buffer operations out Dave Chinner
@ 2013-09-30 3:15 ` Dave Chinner
2013-09-30 3:15 ` [PATCH 12/32] libxfs: unify xfs_btree.c with kernel code Dave Chinner
` (20 subsequent siblings)
31 siblings, 0 replies; 56+ messages in thread
From: Dave Chinner @ 2013-09-30 3:15 UTC (permalink / raw)
To: xfs
From: Dave Chinner <dchinner@redhat.com>
Currently the xfs_inode.h header has a dependency on the definition
of the BMAP btree records as the inode fork includes an array of
xfs_bmbt_rec_host_t objects in it's definition.
Move all the btree format definitions from xfs_btree.h,
xfs_bmap_btree.h, xfs_alloc_btree.h and xfs_ialloc_btree.h to
xfs_format.h to continue the process of centralising the on-disk
format definitions. With this done, the xfs inode definitions are no
longer dependent on btree header files.
The enables a massive culling of unnecessary includes, with close to
200 #include directives removed from the XFS kernel code base.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
include/xfs_alloc_btree.h | 33 ------
include/xfs_bmap_btree.h | 103 -----------------
include/xfs_btree.h | 80 -------------
include/xfs_format.h | 281 +++++++++++++++++++++++++++++++++++++++++++++
include/xfs_ialloc.h | 3 +-
include/xfs_ialloc_btree.h | 49 --------
include/xfs_inode_fork.h | 1 +
7 files changed, 284 insertions(+), 266 deletions(-)
diff --git a/include/xfs_alloc_btree.h b/include/xfs_alloc_btree.h
index 72676c3..45e189e 100644
--- a/include/xfs_alloc_btree.h
+++ b/include/xfs_alloc_btree.h
@@ -27,39 +27,6 @@ struct xfs_btree_cur;
struct xfs_mount;
/*
- * There are two on-disk btrees, one sorted by blockno and one sorted
- * by blockcount and blockno. All blocks look the same to make the code
- * simpler; if we have time later, we'll make the optimizations.
- */
-#define XFS_ABTB_MAGIC 0x41425442 /* 'ABTB' for bno tree */
-#define XFS_ABTB_CRC_MAGIC 0x41423342 /* 'AB3B' */
-#define XFS_ABTC_MAGIC 0x41425443 /* 'ABTC' for cnt tree */
-#define XFS_ABTC_CRC_MAGIC 0x41423343 /* 'AB3C' */
-
-/*
- * Data record/key structure
- */
-typedef struct xfs_alloc_rec {
- __be32 ar_startblock; /* starting block number */
- __be32 ar_blockcount; /* count of free blocks */
-} xfs_alloc_rec_t, xfs_alloc_key_t;
-
-typedef struct xfs_alloc_rec_incore {
- xfs_agblock_t ar_startblock; /* starting block number */
- xfs_extlen_t ar_blockcount; /* count of free blocks */
-} xfs_alloc_rec_incore_t;
-
-/* btree pointer type */
-typedef __be32 xfs_alloc_ptr_t;
-
-/*
- * Block numbers in the AG:
- * SB is sector 0, AGF is sector 1, AGI is sector 2, AGFL is sector 3.
- */
-#define XFS_BNO_BLOCK(mp) ((xfs_agblock_t)(XFS_AGFL_BLOCK(mp) + 1))
-#define XFS_CNT_BLOCK(mp) ((xfs_agblock_t)(XFS_BNO_BLOCK(mp) + 1))
-
-/*
* Btree block header size depends on a superblock flag.
*/
#define XFS_ALLOC_BLOCK_LEN(mp) \
diff --git a/include/xfs_bmap_btree.h b/include/xfs_bmap_btree.h
index e307978..2379d33 100644
--- a/include/xfs_bmap_btree.h
+++ b/include/xfs_bmap_btree.h
@@ -18,9 +18,6 @@
#ifndef __XFS_BMAP_BTREE_H__
#define __XFS_BMAP_BTREE_H__
-#define XFS_BMAP_MAGIC 0x424d4150 /* 'BMAP' */
-#define XFS_BMAP_CRC_MAGIC 0x424d4133 /* 'BMA3' */
-
struct xfs_btree_cur;
struct xfs_btree_block;
struct xfs_mount;
@@ -28,85 +25,6 @@ struct xfs_inode;
struct xfs_trans;
/*
- * Bmap root header, on-disk form only.
- */
-typedef struct xfs_bmdr_block {
- __be16 bb_level; /* 0 is a leaf */
- __be16 bb_numrecs; /* current # of data records */
-} xfs_bmdr_block_t;
-
-/*
- * Bmap btree record and extent descriptor.
- * l0:63 is an extent flag (value 1 indicates non-normal).
- * l0:9-62 are startoff.
- * l0:0-8 and l1:21-63 are startblock.
- * l1:0-20 are blockcount.
- */
-#define BMBT_EXNTFLAG_BITLEN 1
-#define BMBT_STARTOFF_BITLEN 54
-#define BMBT_STARTBLOCK_BITLEN 52
-#define BMBT_BLOCKCOUNT_BITLEN 21
-
-typedef struct xfs_bmbt_rec {
- __be64 l0, l1;
-} xfs_bmbt_rec_t;
-
-typedef __uint64_t xfs_bmbt_rec_base_t; /* use this for casts */
-typedef xfs_bmbt_rec_t xfs_bmdr_rec_t;
-
-typedef struct xfs_bmbt_rec_host {
- __uint64_t l0, l1;
-} xfs_bmbt_rec_host_t;
-
-/*
- * Values and macros for delayed-allocation startblock fields.
- */
-#define STARTBLOCKVALBITS 17
-#define STARTBLOCKMASKBITS (15 + XFS_BIG_BLKNOS * 20)
-#define DSTARTBLOCKMASKBITS (15 + 20)
-#define STARTBLOCKMASK \
- (((((xfs_fsblock_t)1) << STARTBLOCKMASKBITS) - 1) << STARTBLOCKVALBITS)
-#define DSTARTBLOCKMASK \
- (((((xfs_dfsbno_t)1) << DSTARTBLOCKMASKBITS) - 1) << STARTBLOCKVALBITS)
-
-static inline int isnullstartblock(xfs_fsblock_t x)
-{
- return ((x) & STARTBLOCKMASK) == STARTBLOCKMASK;
-}
-
-static inline int isnulldstartblock(xfs_dfsbno_t x)
-{
- return ((x) & DSTARTBLOCKMASK) == DSTARTBLOCKMASK;
-}
-
-static inline xfs_fsblock_t nullstartblock(int k)
-{
- ASSERT(k < (1 << STARTBLOCKVALBITS));
- return STARTBLOCKMASK | (k);
-}
-
-static inline xfs_filblks_t startblockval(xfs_fsblock_t x)
-{
- return (xfs_filblks_t)((x) & ~STARTBLOCKMASK);
-}
-
-/*
- * Possible extent formats.
- */
-typedef enum {
- XFS_EXTFMT_NOSTATE = 0,
- XFS_EXTFMT_HASSTATE
-} xfs_exntfmt_t;
-
-/*
- * Possible extent states.
- */
-typedef enum {
- XFS_EXT_NORM, XFS_EXT_UNWRITTEN,
- XFS_EXT_DMAPI_OFFLINE, XFS_EXT_INVALID
-} xfs_exntst_t;
-
-/*
* Extent state and extent format macros.
*/
#define XFS_EXTFMT_INODE(x) \
@@ -115,27 +33,6 @@ typedef enum {
#define ISUNWRITTEN(x) ((x)->br_state == XFS_EXT_UNWRITTEN)
/*
- * Incore version of above.
- */
-typedef struct xfs_bmbt_irec
-{
- xfs_fileoff_t br_startoff; /* starting file offset */
- xfs_fsblock_t br_startblock; /* starting block number */
- xfs_filblks_t br_blockcount; /* number of blocks */
- xfs_exntst_t br_state; /* extent state */
-} xfs_bmbt_irec_t;
-
-/*
- * Key structure for non-leaf levels of the tree.
- */
-typedef struct xfs_bmbt_key {
- __be64 br_startoff; /* starting file offset */
-} xfs_bmbt_key_t, xfs_bmdr_key_t;
-
-/* btree pointer type */
-typedef __be64 xfs_bmbt_ptr_t, xfs_bmdr_ptr_t;
-
-/*
* Btree block header size depends on a superblock flag.
*/
#define XFS_BMBT_BLOCK_LEN(mp) \
diff --git a/include/xfs_btree.h b/include/xfs_btree.h
index b55af99..227bfa5 100644
--- a/include/xfs_btree.h
+++ b/include/xfs_btree.h
@@ -39,86 +39,6 @@ extern kmem_zone_t *xfs_btree_cur_zone;
#define XFS_BTNUM_INO ((xfs_btnum_t)XFS_BTNUM_INOi)
/*
- * Generic btree header.
- *
- * This is a combination of the actual format used on disk for short and long
- * format btrees. The first three fields are shared by both format, but the
- * pointers are different and should be used with care.
- *
- * To get the size of the actual short or long form headers please use the size
- * macros below. Never use sizeof(xfs_btree_block).
- *
- * The blkno, crc, lsn, owner and uuid fields are only available in filesystems
- * with the crc feature bit, and all accesses to them must be conditional on
- * that flag.
- */
-struct xfs_btree_block {
- __be32 bb_magic; /* magic number for block type */
- __be16 bb_level; /* 0 is a leaf */
- __be16 bb_numrecs; /* current # of data records */
- union {
- struct {
- __be32 bb_leftsib;
- __be32 bb_rightsib;
-
- __be64 bb_blkno;
- __be64 bb_lsn;
- uuid_t bb_uuid;
- __be32 bb_owner;
- __le32 bb_crc;
- } s; /* short form pointers */
- struct {
- __be64 bb_leftsib;
- __be64 bb_rightsib;
-
- __be64 bb_blkno;
- __be64 bb_lsn;
- uuid_t bb_uuid;
- __be64 bb_owner;
- __le32 bb_crc;
- __be32 bb_pad; /* padding for alignment */
- } l; /* long form pointers */
- } bb_u; /* rest */
-};
-
-#define XFS_BTREE_SBLOCK_LEN 16 /* size of a short form block */
-#define XFS_BTREE_LBLOCK_LEN 24 /* size of a long form block */
-
-/* sizes of CRC enabled btree blocks */
-#define XFS_BTREE_SBLOCK_CRC_LEN (XFS_BTREE_SBLOCK_LEN + 40)
-#define XFS_BTREE_LBLOCK_CRC_LEN (XFS_BTREE_LBLOCK_LEN + 48)
-
-#define XFS_BTREE_SBLOCK_CRC_OFF \
- offsetof(struct xfs_btree_block, bb_u.s.bb_crc)
-#define XFS_BTREE_LBLOCK_CRC_OFF \
- offsetof(struct xfs_btree_block, bb_u.l.bb_crc)
-
-/*
- * Generic key, ptr and record wrapper structures.
- *
- * These are disk format structures, and are converted where necessary
- * by the btree specific code that needs to interpret them.
- */
-union xfs_btree_ptr {
- __be32 s; /* short form ptr */
- __be64 l; /* long form ptr */
-};
-
-union xfs_btree_key {
- xfs_bmbt_key_t bmbt;
- xfs_bmdr_key_t bmbr; /* bmbt root block */
- xfs_alloc_key_t alloc;
- xfs_inobt_key_t inobt;
-};
-
-union xfs_btree_rec {
- xfs_bmbt_rec_t bmbt;
- xfs_bmdr_rec_t bmbr; /* bmbt root block */
- xfs_alloc_rec_t alloc;
- xfs_inobt_rec_t inobt;
-};
-
-/*
* For logging record fields.
*/
#define XFS_BB_MAGIC 0x01
diff --git a/include/xfs_format.h b/include/xfs_format.h
index a790428..997c770 100644
--- a/include/xfs_format.h
+++ b/include/xfs_format.h
@@ -156,4 +156,285 @@ struct xfs_dsymlink_hdr {
((bufsize) - (xfs_sb_version_hascrc(&(mp)->m_sb) ? \
sizeof(struct xfs_dsymlink_hdr) : 0))
+
+/*
+ * Allocation Btree format definitions
+ *
+ * There are two on-disk btrees, one sorted by blockno and one sorted
+ * by blockcount and blockno. All blocks look the same to make the code
+ * simpler; if we have time later, we'll make the optimizations.
+ */
+#define XFS_ABTB_MAGIC 0x41425442 /* 'ABTB' for bno tree */
+#define XFS_ABTB_CRC_MAGIC 0x41423342 /* 'AB3B' */
+#define XFS_ABTC_MAGIC 0x41425443 /* 'ABTC' for cnt tree */
+#define XFS_ABTC_CRC_MAGIC 0x41423343 /* 'AB3C' */
+
+/*
+ * Data record/key structure
+ */
+typedef struct xfs_alloc_rec {
+ __be32 ar_startblock; /* starting block number */
+ __be32 ar_blockcount; /* count of free blocks */
+} xfs_alloc_rec_t, xfs_alloc_key_t;
+
+typedef struct xfs_alloc_rec_incore {
+ xfs_agblock_t ar_startblock; /* starting block number */
+ xfs_extlen_t ar_blockcount; /* count of free blocks */
+} xfs_alloc_rec_incore_t;
+
+/* btree pointer type */
+typedef __be32 xfs_alloc_ptr_t;
+
+/*
+ * Block numbers in the AG:
+ * SB is sector 0, AGF is sector 1, AGI is sector 2, AGFL is sector 3.
+ */
+#define XFS_BNO_BLOCK(mp) ((xfs_agblock_t)(XFS_AGFL_BLOCK(mp) + 1))
+#define XFS_CNT_BLOCK(mp) ((xfs_agblock_t)(XFS_BNO_BLOCK(mp) + 1))
+
+
+/*
+ * Inode Allocation Btree format definitions
+ *
+ * There is a btree for the inode map per allocation group.
+ */
+#define XFS_IBT_MAGIC 0x49414254 /* 'IABT' */
+#define XFS_IBT_CRC_MAGIC 0x49414233 /* 'IAB3' */
+
+typedef __uint64_t xfs_inofree_t;
+#define XFS_INODES_PER_CHUNK (NBBY * sizeof(xfs_inofree_t))
+#define XFS_INODES_PER_CHUNK_LOG (XFS_NBBYLOG + 3)
+#define XFS_INOBT_ALL_FREE ((xfs_inofree_t)-1)
+#define XFS_INOBT_MASK(i) ((xfs_inofree_t)1 << (i))
+
+static inline xfs_inofree_t xfs_inobt_maskn(int i, int n)
+{
+ return ((n >= XFS_INODES_PER_CHUNK ? 0 : XFS_INOBT_MASK(n)) - 1) << i;
+}
+
+/*
+ * Data record structure
+ */
+typedef struct xfs_inobt_rec {
+ __be32 ir_startino; /* starting inode number */
+ __be32 ir_freecount; /* count of free inodes (set bits) */
+ __be64 ir_free; /* free inode mask */
+} xfs_inobt_rec_t;
+
+typedef struct xfs_inobt_rec_incore {
+ xfs_agino_t ir_startino; /* starting inode number */
+ __int32_t ir_freecount; /* count of free inodes (set bits) */
+ xfs_inofree_t ir_free; /* free inode mask */
+} xfs_inobt_rec_incore_t;
+
+
+/*
+ * Key structure
+ */
+typedef struct xfs_inobt_key {
+ __be32 ir_startino; /* starting inode number */
+} xfs_inobt_key_t;
+
+/* btree pointer type */
+typedef __be32 xfs_inobt_ptr_t;
+
+/*
+ * block numbers in the AG.
+ */
+#define XFS_IBT_BLOCK(mp) ((xfs_agblock_t)(XFS_CNT_BLOCK(mp) + 1))
+#define XFS_PREALLOC_BLOCKS(mp) ((xfs_agblock_t)(XFS_IBT_BLOCK(mp) + 1))
+
+
+
+/*
+ * BMAP Btree format definitions
+ *
+ * This includes both the root block definition that sits inside an inode fork
+ * and the record/pointer formats for the leaf/node in the blocks.
+ */
+#define XFS_BMAP_MAGIC 0x424d4150 /* 'BMAP' */
+#define XFS_BMAP_CRC_MAGIC 0x424d4133 /* 'BMA3' */
+
+/*
+ * Bmap root header, on-disk form only.
+ */
+typedef struct xfs_bmdr_block {
+ __be16 bb_level; /* 0 is a leaf */
+ __be16 bb_numrecs; /* current # of data records */
+} xfs_bmdr_block_t;
+
+/*
+ * Bmap btree record and extent descriptor.
+ * l0:63 is an extent flag (value 1 indicates non-normal).
+ * l0:9-62 are startoff.
+ * l0:0-8 and l1:21-63 are startblock.
+ * l1:0-20 are blockcount.
+ */
+#define BMBT_EXNTFLAG_BITLEN 1
+#define BMBT_STARTOFF_BITLEN 54
+#define BMBT_STARTBLOCK_BITLEN 52
+#define BMBT_BLOCKCOUNT_BITLEN 21
+
+typedef struct xfs_bmbt_rec {
+ __be64 l0, l1;
+} xfs_bmbt_rec_t;
+
+typedef __uint64_t xfs_bmbt_rec_base_t; /* use this for casts */
+typedef xfs_bmbt_rec_t xfs_bmdr_rec_t;
+
+typedef struct xfs_bmbt_rec_host {
+ __uint64_t l0, l1;
+} xfs_bmbt_rec_host_t;
+
+/*
+ * Values and macros for delayed-allocation startblock fields.
+ */
+#define STARTBLOCKVALBITS 17
+#define STARTBLOCKMASKBITS (15 + XFS_BIG_BLKNOS * 20)
+#define DSTARTBLOCKMASKBITS (15 + 20)
+#define STARTBLOCKMASK \
+ (((((xfs_fsblock_t)1) << STARTBLOCKMASKBITS) - 1) << STARTBLOCKVALBITS)
+#define DSTARTBLOCKMASK \
+ (((((xfs_dfsbno_t)1) << DSTARTBLOCKMASKBITS) - 1) << STARTBLOCKVALBITS)
+
+static inline int isnullstartblock(xfs_fsblock_t x)
+{
+ return ((x) & STARTBLOCKMASK) == STARTBLOCKMASK;
+}
+
+static inline int isnulldstartblock(xfs_dfsbno_t x)
+{
+ return ((x) & DSTARTBLOCKMASK) == DSTARTBLOCKMASK;
+}
+
+static inline xfs_fsblock_t nullstartblock(int k)
+{
+ ASSERT(k < (1 << STARTBLOCKVALBITS));
+ return STARTBLOCKMASK | (k);
+}
+
+static inline xfs_filblks_t startblockval(xfs_fsblock_t x)
+{
+ return (xfs_filblks_t)((x) & ~STARTBLOCKMASK);
+}
+
+/*
+ * Possible extent formats.
+ */
+typedef enum {
+ XFS_EXTFMT_NOSTATE = 0,
+ XFS_EXTFMT_HASSTATE
+} xfs_exntfmt_t;
+
+/*
+ * Possible extent states.
+ */
+typedef enum {
+ XFS_EXT_NORM, XFS_EXT_UNWRITTEN,
+ XFS_EXT_DMAPI_OFFLINE, XFS_EXT_INVALID
+} xfs_exntst_t;
+
+/*
+ * Incore version of above.
+ */
+typedef struct xfs_bmbt_irec
+{
+ xfs_fileoff_t br_startoff; /* starting file offset */
+ xfs_fsblock_t br_startblock; /* starting block number */
+ xfs_filblks_t br_blockcount; /* number of blocks */
+ xfs_exntst_t br_state; /* extent state */
+} xfs_bmbt_irec_t;
+
+/*
+ * Key structure for non-leaf levels of the tree.
+ */
+typedef struct xfs_bmbt_key {
+ __be64 br_startoff; /* starting file offset */
+} xfs_bmbt_key_t, xfs_bmdr_key_t;
+
+/* btree pointer type */
+typedef __be64 xfs_bmbt_ptr_t, xfs_bmdr_ptr_t;
+
+
+/*
+ * Generic Btree block format definitions
+ *
+ * This is a combination of the actual format used on disk for short and long
+ * format btrees. The first three fields are shared by both format, but the
+ * pointers are different and should be used with care.
+ *
+ * To get the size of the actual short or long form headers please use the size
+ * macros below. Never use sizeof(xfs_btree_block).
+ *
+ * The blkno, crc, lsn, owner and uuid fields are only available in filesystems
+ * with the crc feature bit, and all accesses to them must be conditional on
+ * that flag.
+ */
+struct xfs_btree_block {
+ __be32 bb_magic; /* magic number for block type */
+ __be16 bb_level; /* 0 is a leaf */
+ __be16 bb_numrecs; /* current # of data records */
+ union {
+ struct {
+ __be32 bb_leftsib;
+ __be32 bb_rightsib;
+
+ __be64 bb_blkno;
+ __be64 bb_lsn;
+ uuid_t bb_uuid;
+ __be32 bb_owner;
+ __le32 bb_crc;
+ } s; /* short form pointers */
+ struct {
+ __be64 bb_leftsib;
+ __be64 bb_rightsib;
+
+ __be64 bb_blkno;
+ __be64 bb_lsn;
+ uuid_t bb_uuid;
+ __be64 bb_owner;
+ __le32 bb_crc;
+ __be32 bb_pad; /* padding for alignment */
+ } l; /* long form pointers */
+ } bb_u; /* rest */
+};
+
+#define XFS_BTREE_SBLOCK_LEN 16 /* size of a short form block */
+#define XFS_BTREE_LBLOCK_LEN 24 /* size of a long form block */
+
+/* sizes of CRC enabled btree blocks */
+#define XFS_BTREE_SBLOCK_CRC_LEN (XFS_BTREE_SBLOCK_LEN + 40)
+#define XFS_BTREE_LBLOCK_CRC_LEN (XFS_BTREE_LBLOCK_LEN + 48)
+
+#define XFS_BTREE_SBLOCK_CRC_OFF \
+ offsetof(struct xfs_btree_block, bb_u.s.bb_crc)
+#define XFS_BTREE_LBLOCK_CRC_OFF \
+ offsetof(struct xfs_btree_block, bb_u.l.bb_crc)
+
+/*
+ * Generic key, ptr and record wrapper structures.
+ *
+ * These are disk format structures, and are converted where necessary
+ * by the btree specific code that needs to interpret them.
+ */
+union xfs_btree_ptr {
+ __be32 s; /* short form ptr */
+ __be64 l; /* long form ptr */
+};
+
+union xfs_btree_key {
+ xfs_bmbt_key_t bmbt;
+ xfs_bmdr_key_t bmbr; /* bmbt root block */
+ xfs_alloc_key_t alloc;
+ xfs_inobt_key_t inobt;
+};
+
+union xfs_btree_rec {
+ xfs_bmbt_rec_t bmbt;
+ xfs_bmdr_rec_t bmbr; /* bmbt root block */
+ xfs_alloc_rec_t alloc;
+ xfs_inobt_rec_t inobt;
+};
+
+
#endif /* __XFS_FORMAT_H__ */
diff --git a/include/xfs_ialloc.h b/include/xfs_ialloc.h
index 1557798..a8f76a5 100644
--- a/include/xfs_ialloc.h
+++ b/include/xfs_ialloc.h
@@ -23,6 +23,7 @@ struct xfs_dinode;
struct xfs_imap;
struct xfs_mount;
struct xfs_trans;
+struct xfs_btree_cur;
/*
* Allocation parameters for inode allocation.
@@ -42,7 +43,7 @@ struct xfs_trans;
static inline struct xfs_dinode *
xfs_make_iptr(struct xfs_mount *mp, struct xfs_buf *b, int o)
{
- return (xfs_dinode_t *)
+ return (struct xfs_dinode *)
(xfs_buf_offset(b, o << (mp)->m_sb.sb_inodelog));
}
diff --git a/include/xfs_ialloc_btree.h b/include/xfs_ialloc_btree.h
index cfbfe46..f38b220 100644
--- a/include/xfs_ialloc_btree.h
+++ b/include/xfs_ialloc_btree.h
@@ -27,55 +27,6 @@ struct xfs_btree_cur;
struct xfs_mount;
/*
- * There is a btree for the inode map per allocation group.
- */
-#define XFS_IBT_MAGIC 0x49414254 /* 'IABT' */
-#define XFS_IBT_CRC_MAGIC 0x49414233 /* 'IAB3' */
-
-typedef __uint64_t xfs_inofree_t;
-#define XFS_INODES_PER_CHUNK (NBBY * sizeof(xfs_inofree_t))
-#define XFS_INODES_PER_CHUNK_LOG (XFS_NBBYLOG + 3)
-#define XFS_INOBT_ALL_FREE ((xfs_inofree_t)-1)
-#define XFS_INOBT_MASK(i) ((xfs_inofree_t)1 << (i))
-
-static inline xfs_inofree_t xfs_inobt_maskn(int i, int n)
-{
- return ((n >= XFS_INODES_PER_CHUNK ? 0 : XFS_INOBT_MASK(n)) - 1) << i;
-}
-
-/*
- * Data record structure
- */
-typedef struct xfs_inobt_rec {
- __be32 ir_startino; /* starting inode number */
- __be32 ir_freecount; /* count of free inodes (set bits) */
- __be64 ir_free; /* free inode mask */
-} xfs_inobt_rec_t;
-
-typedef struct xfs_inobt_rec_incore {
- xfs_agino_t ir_startino; /* starting inode number */
- __int32_t ir_freecount; /* count of free inodes (set bits) */
- xfs_inofree_t ir_free; /* free inode mask */
-} xfs_inobt_rec_incore_t;
-
-
-/*
- * Key structure
- */
-typedef struct xfs_inobt_key {
- __be32 ir_startino; /* starting inode number */
-} xfs_inobt_key_t;
-
-/* btree pointer type */
-typedef __be32 xfs_inobt_ptr_t;
-
-/*
- * block numbers in the AG.
- */
-#define XFS_IBT_BLOCK(mp) ((xfs_agblock_t)(XFS_CNT_BLOCK(mp) + 1))
-#define XFS_PREALLOC_BLOCKS(mp) ((xfs_agblock_t)(XFS_IBT_BLOCK(mp) + 1))
-
-/*
* Btree block header size depends on a superblock flag.
*/
#define XFS_INOBT_BLOCK_LEN(mp) \
diff --git a/include/xfs_inode_fork.h b/include/xfs_inode_fork.h
index 28661a0..eb329a1 100644
--- a/include/xfs_inode_fork.h
+++ b/include/xfs_inode_fork.h
@@ -19,6 +19,7 @@
#define __XFS_INODE_FORK_H__
struct xfs_inode_log_item;
+struct xfs_dinode;
/*
* The following xfs_ext_irec_t struct introduces a second (top) level
--
1.8.3.2
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 12/32] libxfs: unify xfs_btree.c with kernel code
[not found] <1380510944-8571-1-git-send-email-david@fromorbit.com>
` (10 preceding siblings ...)
2013-09-30 3:15 ` [PATCH 11/32] xfs: decouple inode and bmap btree header files Dave Chinner
@ 2013-09-30 3:15 ` Dave Chinner
2013-09-30 3:15 ` [PATCH 13/32] libxfs: bmap btree owner swap support Dave Chinner
` (19 subsequent siblings)
31 siblings, 0 replies; 56+ messages in thread
From: Dave Chinner @ 2013-09-30 3:15 UTC (permalink / raw)
To: xfs
From: Dave Chinner <dchinner@redhat.com>
The libxfs/xfs_btree.c code does not contain a small amount of code
for btree block readahead that the kernel code does. Instead, it
short circuits it at a higher layer and doesn't include the lower
layer functions. There is no harm in calling the lower lay functions
and have them do nothing, and doing so unifies the kernel and
userspace code.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
libxfs/xfs.h | 8 +++++---
libxfs/xfs_btree.c | 48 +++++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 48 insertions(+), 8 deletions(-)
diff --git a/libxfs/xfs.h b/libxfs/xfs.h
index 31acf1b..364fd83 100644
--- a/libxfs/xfs.h
+++ b/libxfs/xfs.h
@@ -319,10 +319,12 @@ roundup_64(__uint64_t x, __uint32_t y)
#define xfs_trans_buf_copy_type(dbp, sbp)
-#define xfs_buf_readahead(a,b,c,ops) ((void) 0) /* no readahead */
+/* no readahead, need to avoid set-but-unused var warnings. */
+#define xfs_buf_readahead(a,d,c,ops) ({ \
+ xfs_daddr_t __d = d; \
+ __d = __d; /* no set-but-unused warning */ \
+})
#define xfs_buf_readahead_map(a,b,c,ops) ((void) 0) /* no readahead */
-#define xfs_btree_reada_bufl(m,fsb,c,ops) ((void) 0)
-#define xfs_btree_reada_bufs(m,fsb,c,x,ops) ((void) 0)
#define xfs_buftrace(x,y) ((void) 0) /* debug only */
#define xfs_cmn_err(tag,level,mp,fmt,args...) cmn_err(level,fmt, ## args)
diff --git a/libxfs/xfs_btree.c b/libxfs/xfs_btree.c
index 0099926..ce149ad 100644
--- a/libxfs/xfs_btree.c
+++ b/libxfs/xfs_btree.c
@@ -396,7 +396,6 @@ static inline size_t xfs_btree_block_len(struct xfs_btree_cur *cur)
return XFS_BTREE_LBLOCK_CRC_LEN;
return XFS_BTREE_LBLOCK_LEN;
}
-
if (cur->bc_flags & XFS_BTREE_CRC_BLOCKS)
return XFS_BTREE_SBLOCK_CRC_LEN;
return XFS_BTREE_SBLOCK_LEN;
@@ -493,7 +492,7 @@ xfs_btree_ptr_addr(
}
/*
- * Get a the root block which is stored in the inode.
+ * Get the root block which is stored in the inode.
*
* For now this btree implementation assumes the btree root is always
* stored in the if_broot field of an inode fork.
@@ -716,6 +715,46 @@ xfs_btree_read_bufl(
return 0;
}
+/*
+ * Read-ahead the block, don't wait for it, don't return a buffer.
+ * Long-form addressing.
+ */
+/* ARGSUSED */
+void
+xfs_btree_reada_bufl(
+ struct xfs_mount *mp, /* file system mount point */
+ xfs_fsblock_t fsbno, /* file system block number */
+ xfs_extlen_t count, /* count of filesystem blocks */
+ const struct xfs_buf_ops *ops)
+{
+ xfs_daddr_t d;
+
+ ASSERT(fsbno != NULLFSBLOCK);
+ d = XFS_FSB_TO_DADDR(mp, fsbno);
+ xfs_buf_readahead(mp->m_ddev_targp, d, mp->m_bsize * count, ops);
+}
+
+/*
+ * Read-ahead the block, don't wait for it, don't return a buffer.
+ * Short-form addressing.
+ */
+/* ARGSUSED */
+void
+xfs_btree_reada_bufs(
+ struct xfs_mount *mp, /* file system mount point */
+ xfs_agnumber_t agno, /* allocation group number */
+ xfs_agblock_t agbno, /* allocation group block number */
+ xfs_extlen_t count, /* count of filesystem blocks */
+ const struct xfs_buf_ops *ops)
+{
+ xfs_daddr_t d;
+
+ ASSERT(agno != NULLAGNUMBER);
+ ASSERT(agbno != NULLAGBLOCK);
+ d = XFS_AGB_TO_DADDR(mp, agno, agbno);
+ xfs_buf_readahead(mp->m_ddev_targp, d, mp->m_bsize * count, ops);
+}
+
STATIC int
xfs_btree_readahead_lblock(
struct xfs_btree_cur *cur,
@@ -1339,7 +1378,7 @@ xfs_btree_log_block(
* We don't log the CRC when updating a btree
* block but instead recreate it during log
* recovery. As the log buffers have checksums
- * of their this is safe and avoids logging a crc
+ * of their own this is safe and avoids logging a crc
* update in a lot of places.
*/
if (fields == XFS_BB_ALL_BITS)
@@ -1629,7 +1668,7 @@ xfs_lookup_get_search_key(
/*
* Lookup the record. The cursor is made to point to it, based on dir.
- * Return 0 if can't find any such record, 1 for success.
+ * stat is set to 0 if can't find any such record, 1 for success.
*/
int /* error */
xfs_btree_lookup(
@@ -2701,7 +2740,6 @@ xfs_btree_make_block_unfull(
if (numrecs < cur->bc_ops->get_dmaxrecs(cur, level)) {
/* A root block that can be made bigger. */
-
xfs_iroot_realloc(ip, 1, cur->bc_private.b.whichfork);
} else {
/* A root block that needs replacing */
--
1.8.3.2
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 13/32] libxfs: bmap btree owner swap support
[not found] <1380510944-8571-1-git-send-email-david@fromorbit.com>
` (11 preceding siblings ...)
2013-09-30 3:15 ` [PATCH 12/32] libxfs: unify xfs_btree.c with kernel code Dave Chinner
@ 2013-09-30 3:15 ` Dave Chinner
2013-09-30 3:15 ` [PATCH 14/32] libxfs: xfs_rtalloc.c becomes xfs_rtbitmap.c Dave Chinner
` (18 subsequent siblings)
31 siblings, 0 replies; 56+ messages in thread
From: Dave Chinner @ 2013-09-30 3:15 UTC (permalink / raw)
To: xfs
From: Dave Chinner <dchinner@redhat.com>
For CRC enabled filesystems, we can't just swap inode forks from one
inode to another when defragmenting a file - the blocks in the inode
fork bmap btree contain pointers back to the owner inode. Hence if
we are to swap the inode forks we have to atomically modify every
block in the btree during the transaction.
This patch brings across the kernel code for doing the owner
swap of an entire fork - something that we are likely to end up
needing in xfs_repair when reparenting stray inodes to lost+found -
without all the associated swap extents transaction and recovery
cruft as those parts are not needed in userspace.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
include/xfs_bmap_btree.h | 4 ++
include/xfs_btree.h | 19 ++++--
include/xfs_inode_buf.h | 18 ++---
include/xfs_log_format.h | 8 ++-
libxfs/xfs_bmap_btree.c | 44 ++++++++++++
libxfs/xfs_btree.c | 170 ++++++++++++++++++++++++++++++++++++++++++-----
6 files changed, 227 insertions(+), 36 deletions(-)
diff --git a/include/xfs_bmap_btree.h b/include/xfs_bmap_btree.h
index 2379d33..6e42e1e 100644
--- a/include/xfs_bmap_btree.h
+++ b/include/xfs_bmap_btree.h
@@ -133,6 +133,10 @@ extern int xfs_bmbt_get_maxrecs(struct xfs_btree_cur *, int level);
extern int xfs_bmdr_maxrecs(struct xfs_mount *, int blocklen, int leaf);
extern int xfs_bmbt_maxrecs(struct xfs_mount *, int blocklen, int leaf);
+extern int xfs_bmbt_change_owner(struct xfs_trans *tp, struct xfs_inode *ip,
+ int whichfork, xfs_ino_t new_owner,
+ struct list_head *buffer_list);
+
extern struct xfs_btree_cur *xfs_bmbt_init_cursor(struct xfs_mount *,
struct xfs_trans *, struct xfs_inode *, int);
diff --git a/include/xfs_btree.h b/include/xfs_btree.h
index 227bfa5..6afe0b2 100644
--- a/include/xfs_btree.h
+++ b/include/xfs_btree.h
@@ -41,15 +41,18 @@ extern kmem_zone_t *xfs_btree_cur_zone;
/*
* For logging record fields.
*/
-#define XFS_BB_MAGIC 0x01
-#define XFS_BB_LEVEL 0x02
-#define XFS_BB_NUMRECS 0x04
-#define XFS_BB_LEFTSIB 0x08
-#define XFS_BB_RIGHTSIB 0x10
-#define XFS_BB_BLKNO 0x20
+#define XFS_BB_MAGIC (1 << 0)
+#define XFS_BB_LEVEL (1 << 1)
+#define XFS_BB_NUMRECS (1 << 2)
+#define XFS_BB_LEFTSIB (1 << 3)
+#define XFS_BB_RIGHTSIB (1 << 4)
+#define XFS_BB_BLKNO (1 << 5)
+#define XFS_BB_LSN (1 << 6)
+#define XFS_BB_UUID (1 << 7)
+#define XFS_BB_OWNER (1 << 8)
#define XFS_BB_NUM_BITS 5
#define XFS_BB_ALL_BITS ((1 << XFS_BB_NUM_BITS) - 1)
-#define XFS_BB_NUM_BITS_CRC 8
+#define XFS_BB_NUM_BITS_CRC 9
#define XFS_BB_ALL_BITS_CRC ((1 << XFS_BB_NUM_BITS_CRC) - 1)
/*
@@ -381,6 +384,8 @@ int xfs_btree_new_iroot(struct xfs_btree_cur *, int *, int *);
int xfs_btree_insert(struct xfs_btree_cur *, int *);
int xfs_btree_delete(struct xfs_btree_cur *, int *);
int xfs_btree_get_rec(struct xfs_btree_cur *, union xfs_btree_rec **, int *);
+int xfs_btree_change_owner(struct xfs_btree_cur *cur, __uint64_t new_owner,
+ struct list_head *buffer_list);
/*
* btree block CRC helpers
diff --git a/include/xfs_inode_buf.h b/include/xfs_inode_buf.h
index e8fd3bd..9308c47 100644
--- a/include/xfs_inode_buf.h
+++ b/include/xfs_inode_buf.h
@@ -32,17 +32,17 @@ struct xfs_imap {
ushort im_boffset; /* inode offset in block in bytes */
};
-int xfs_imap_to_bp(struct xfs_mount *, struct xfs_trans *,
- struct xfs_imap *, struct xfs_dinode **,
- struct xfs_buf **, uint, uint);
-int xfs_iread(struct xfs_mount *, struct xfs_trans *,
- struct xfs_inode *, uint);
-void xfs_dinode_calc_crc(struct xfs_mount *, struct xfs_dinode *);
-void xfs_dinode_to_disk(struct xfs_dinode *,
- struct xfs_icdinode *);
+int xfs_imap_to_bp(struct xfs_mount *, struct xfs_trans *,
+ struct xfs_imap *, struct xfs_dinode **,
+ struct xfs_buf **, uint, uint);
+int xfs_iread(struct xfs_mount *, struct xfs_trans *,
+ struct xfs_inode *, uint);
+void xfs_dinode_calc_crc(struct xfs_mount *, struct xfs_dinode *);
+void xfs_dinode_to_disk(struct xfs_dinode *to, struct xfs_icdinode *from);
+void xfs_dinode_from_disk(struct xfs_icdinode *to, struct xfs_dinode *from);
#if defined(DEBUG)
-void xfs_inobp_check(struct xfs_mount *, struct xfs_buf *);
+void xfs_inobp_check(struct xfs_mount *, struct xfs_buf *);
#else
#define xfs_inobp_check(mp, bp)
#endif /* DEBUG */
diff --git a/include/xfs_log_format.h b/include/xfs_log_format.h
index aeaa715..f0969c7 100644
--- a/include/xfs_log_format.h
+++ b/include/xfs_log_format.h
@@ -302,6 +302,8 @@ typedef struct xfs_inode_log_format_64 {
#define XFS_ILOG_ADATA 0x040 /* log i_af.if_data */
#define XFS_ILOG_AEXT 0x080 /* log i_af.if_extents */
#define XFS_ILOG_ABROOT 0x100 /* log i_af.i_broot */
+#define XFS_ILOG_DOWNER 0x200 /* change the data fork owner on replay */
+#define XFS_ILOG_AOWNER 0x400 /* change the attr fork owner on replay */
/*
@@ -315,7 +317,8 @@ typedef struct xfs_inode_log_format_64 {
#define XFS_ILOG_NONCORE (XFS_ILOG_DDATA | XFS_ILOG_DEXT | \
XFS_ILOG_DBROOT | XFS_ILOG_DEV | \
XFS_ILOG_UUID | XFS_ILOG_ADATA | \
- XFS_ILOG_AEXT | XFS_ILOG_ABROOT)
+ XFS_ILOG_AEXT | XFS_ILOG_ABROOT | \
+ XFS_ILOG_DOWNER | XFS_ILOG_AOWNER)
#define XFS_ILOG_DFORK (XFS_ILOG_DDATA | XFS_ILOG_DEXT | \
XFS_ILOG_DBROOT)
@@ -327,7 +330,8 @@ typedef struct xfs_inode_log_format_64 {
XFS_ILOG_DEXT | XFS_ILOG_DBROOT | \
XFS_ILOG_DEV | XFS_ILOG_UUID | \
XFS_ILOG_ADATA | XFS_ILOG_AEXT | \
- XFS_ILOG_ABROOT | XFS_ILOG_TIMESTAMP)
+ XFS_ILOG_ABROOT | XFS_ILOG_TIMESTAMP | \
+ XFS_ILOG_DOWNER | XFS_ILOG_AOWNER)
static inline int xfs_ilog_fbroot(int w)
{
diff --git a/libxfs/xfs_bmap_btree.c b/libxfs/xfs_bmap_btree.c
index bf214cf..2f6b48a 100644
--- a/libxfs/xfs_bmap_btree.c
+++ b/libxfs/xfs_bmap_btree.c
@@ -999,3 +999,47 @@ xfs_bmdr_maxrecs(
return blocklen / sizeof(xfs_bmdr_rec_t);
return blocklen / (sizeof(xfs_bmdr_key_t) + sizeof(xfs_bmdr_ptr_t));
}
+
+/*
+ * Change the owner of a btree format fork fo the inode passed in. Change it to
+ * the owner of that is passed in so that we can change owners before or after
+ * we switch forks between inodes. The operation that the caller is doing will
+ * determine whether is needs to change owner before or after the switch.
+ *
+ * For demand paged transactional modification, the fork switch should be done
+ * after reading in all the blocks, modifying them and pinning them in the
+ * transaction. For modification when the buffers are already pinned in memory,
+ * the fork switch can be done before changing the owner as we won't need to
+ * validate the owner until the btree buffers are unpinned and writes can occur
+ * again.
+ *
+ * For recovery based ownership change, there is no transactional context and
+ * so a buffer list must be supplied so that we can record the buffers that we
+ * modified for the caller to issue IO on.
+ */
+int
+xfs_bmbt_change_owner(
+ struct xfs_trans *tp,
+ struct xfs_inode *ip,
+ int whichfork,
+ xfs_ino_t new_owner,
+ struct list_head *buffer_list)
+{
+ struct xfs_btree_cur *cur;
+ int error;
+
+ ASSERT(tp || buffer_list);
+ ASSERT(!(tp && buffer_list));
+ if (whichfork == XFS_DATA_FORK)
+ ASSERT(ip->i_d.di_format == XFS_DINODE_FMT_BTREE);
+ else
+ ASSERT(ip->i_d.di_aformat == XFS_DINODE_FMT_BTREE);
+
+ cur = xfs_bmbt_init_cursor(ip->i_mount, tp, ip, whichfork);
+ if (!cur)
+ return ENOMEM;
+
+ error = xfs_btree_change_owner(cur, new_owner, buffer_list);
+ xfs_btree_del_cursor(cur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
+ return error;
+}
diff --git a/libxfs/xfs_btree.c b/libxfs/xfs_btree.c
index ce149ad..2dd6fb7 100644
--- a/libxfs/xfs_btree.c
+++ b/libxfs/xfs_btree.c
@@ -837,6 +837,41 @@ xfs_btree_readahead(
return xfs_btree_readahead_sblock(cur, lr, block);
}
+STATIC xfs_daddr_t
+xfs_btree_ptr_to_daddr(
+ struct xfs_btree_cur *cur,
+ union xfs_btree_ptr *ptr)
+{
+ if (cur->bc_flags & XFS_BTREE_LONG_PTRS) {
+ ASSERT(ptr->l != cpu_to_be64(NULLDFSBNO));
+
+ return XFS_FSB_TO_DADDR(cur->bc_mp, be64_to_cpu(ptr->l));
+ } else {
+ ASSERT(cur->bc_private.a.agno != NULLAGNUMBER);
+ ASSERT(ptr->s != cpu_to_be32(NULLAGBLOCK));
+
+ return XFS_AGB_TO_DADDR(cur->bc_mp, cur->bc_private.a.agno,
+ be32_to_cpu(ptr->s));
+ }
+}
+
+/*
+ * Readahead @count btree blocks at the given @ptr location.
+ *
+ * We don't need to care about long or short form btrees here as we have a
+ * method of converting the ptr directly to a daddr available to us.
+ */
+STATIC void
+xfs_btree_readahead_ptr(
+ struct xfs_btree_cur *cur,
+ union xfs_btree_ptr *ptr,
+ xfs_extlen_t count)
+{
+ xfs_buf_readahead(cur->bc_mp->m_ddev_targp,
+ xfs_btree_ptr_to_daddr(cur, ptr),
+ cur->bc_mp->m_bsize * count, cur->bc_ops->buf_ops);
+}
+
/*
* Set the buffer for level "lev" in the cursor to bp, releasing
* any previous buffer.
@@ -1055,24 +1090,6 @@ xfs_btree_buf_to_ptr(
}
}
-STATIC xfs_daddr_t
-xfs_btree_ptr_to_daddr(
- struct xfs_btree_cur *cur,
- union xfs_btree_ptr *ptr)
-{
- if (cur->bc_flags & XFS_BTREE_LONG_PTRS) {
- ASSERT(ptr->l != cpu_to_be64(NULLDFSBNO));
-
- return XFS_FSB_TO_DADDR(cur->bc_mp, be64_to_cpu(ptr->l));
- } else {
- ASSERT(cur->bc_private.a.agno != NULLAGNUMBER);
- ASSERT(ptr->s != cpu_to_be32(NULLAGBLOCK));
-
- return XFS_AGB_TO_DADDR(cur->bc_mp, cur->bc_private.a.agno,
- be32_to_cpu(ptr->s));
- }
-}
-
STATIC void
xfs_btree_set_refs(
struct xfs_btree_cur *cur,
@@ -3851,3 +3868,120 @@ xfs_btree_get_rec(
*stat = 1;
return 0;
}
+
+/*
+ * Change the owner of a btree.
+ *
+ * The mechanism we use here is ordered buffer logging. Because we don't know
+ * how many buffers were are going to need to modify, we don't really want to
+ * have to make transaction reservations for the worst case of every buffer in a
+ * full size btree as that may be more space that we can fit in the log....
+ *
+ * We do the btree walk in the most optimal manner possible - we have sibling
+ * pointers so we can just walk all the blocks on each level from left to right
+ * in a single pass, and then move to the next level and do the same. We can
+ * also do readahead on the sibling pointers to get IO moving more quickly,
+ * though for slow disks this is unlikely to make much difference to performance
+ * as the amount of CPU work we have to do before moving to the next block is
+ * relatively small.
+ *
+ * For each btree block that we load, modify the owner appropriately, set the
+ * buffer as an ordered buffer and log it appropriately. We need to ensure that
+ * we mark the region we change dirty so that if the buffer is relogged in
+ * a subsequent transaction the changes we make here as an ordered buffer are
+ * correctly relogged in that transaction. If we are in recovery context, then
+ * just queue the modified buffer as delayed write buffer so the transaction
+ * recovery completion writes the changes to disk.
+ */
+static int
+xfs_btree_block_change_owner(
+ struct xfs_btree_cur *cur,
+ int level,
+ __uint64_t new_owner,
+ struct list_head *buffer_list)
+{
+ struct xfs_btree_block *block;
+ struct xfs_buf *bp;
+ union xfs_btree_ptr rptr;
+
+ /* do right sibling readahead */
+ xfs_btree_readahead(cur, level, XFS_BTCUR_RIGHTRA);
+
+ /* modify the owner */
+ block = xfs_btree_get_block(cur, level, &bp);
+ if (cur->bc_flags & XFS_BTREE_LONG_PTRS)
+ block->bb_u.l.bb_owner = cpu_to_be64(new_owner);
+ else
+ block->bb_u.s.bb_owner = cpu_to_be32(new_owner);
+
+ /*
+ * If the block is a root block hosted in an inode, we might not have a
+ * buffer pointer here and we shouldn't attempt to log the change as the
+ * information is already held in the inode and discarded when the root
+ * block is formatted into the on-disk inode fork. We still change it,
+ * though, so everything is consistent in memory.
+ */
+ if (bp) {
+ if (cur->bc_tp) {
+ xfs_trans_ordered_buf(cur->bc_tp, bp);
+ xfs_btree_log_block(cur, bp, XFS_BB_OWNER);
+ } else {
+ xfs_buf_delwri_queue(bp, buffer_list);
+ }
+ } else {
+ ASSERT(cur->bc_flags & XFS_BTREE_ROOT_IN_INODE);
+ ASSERT(level == cur->bc_nlevels - 1);
+ }
+
+ /* now read rh sibling block for next iteration */
+ xfs_btree_get_sibling(cur, block, &rptr, XFS_BB_RIGHTSIB);
+ if (xfs_btree_ptr_is_null(cur, &rptr))
+ return ENOENT;
+
+ return xfs_btree_lookup_get_block(cur, level, &rptr, &block);
+}
+
+int
+xfs_btree_change_owner(
+ struct xfs_btree_cur *cur,
+ __uint64_t new_owner,
+ struct list_head *buffer_list)
+{
+ union xfs_btree_ptr lptr;
+ int level;
+ struct xfs_btree_block *block = NULL;
+ int error = 0;
+
+ cur->bc_ops->init_ptr_from_cur(cur, &lptr);
+
+ /* for each level */
+ for (level = cur->bc_nlevels - 1; level >= 0; level--) {
+ /* grab the left hand block */
+ error = xfs_btree_lookup_get_block(cur, level, &lptr, &block);
+ if (error)
+ return error;
+
+ /* readahead the left most block for the next level down */
+ if (level > 0) {
+ union xfs_btree_ptr *ptr;
+
+ ptr = xfs_btree_ptr_addr(cur, 1, block);
+ xfs_btree_readahead_ptr(cur, ptr, 1);
+
+ /* save for the next iteration of the loop */
+ lptr = *ptr;
+ }
+
+ /* for each buffer in the level */
+ do {
+ error = xfs_btree_block_change_owner(cur, level,
+ new_owner,
+ buffer_list);
+ } while (!error);
+
+ if (error != ENOENT)
+ return error;
+ }
+
+ return 0;
+}
--
1.8.3.2
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 14/32] libxfs: xfs_rtalloc.c becomes xfs_rtbitmap.c
[not found] <1380510944-8571-1-git-send-email-david@fromorbit.com>
` (12 preceding siblings ...)
2013-09-30 3:15 ` [PATCH 13/32] libxfs: bmap btree owner swap support Dave Chinner
@ 2013-09-30 3:15 ` Dave Chinner
2013-09-30 3:15 ` [PATCH 15/32] libxfs: bring across inode buffer readahead verifier changes Dave Chinner
` (17 subsequent siblings)
31 siblings, 0 replies; 56+ messages in thread
From: Dave Chinner @ 2013-09-30 3:15 UTC (permalink / raw)
To: xfs
From: Dave Chinner <dchinner@redhat.com>
To match the split-up of the kernel xfs_rtalloc.c file, convert the
libxfs version of xfs_rtalloc.c to match the newly shared kernel
source file with all the realtime bitmap functions in it,
xfs_rtbitmap.c.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
libxfs/Makefile | 2 +-
libxfs/xfs_rtalloc.c | 776 ----------------------------------------
libxfs/xfs_rtbitmap.c | 951 ++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 952 insertions(+), 777 deletions(-)
delete mode 100644 libxfs/xfs_rtalloc.c
create mode 100644 libxfs/xfs_rtbitmap.c
diff --git a/libxfs/Makefile b/libxfs/Makefile
index 4522218..ae15a5d 100644
--- a/libxfs/Makefile
+++ b/libxfs/Makefile
@@ -35,7 +35,7 @@ CFILES = cache.c \
xfs_inode_fork.c \
xfs_ialloc_btree.c \
xfs_log_rlimit.c \
- xfs_rtalloc.c \
+ xfs_rtbitmap.c \
xfs_sb.c \
xfs_symlink_remote.c \
xfs_trans_resv.c
diff --git a/libxfs/xfs_rtalloc.c b/libxfs/xfs_rtalloc.c
deleted file mode 100644
index f5a90b2..0000000
--- a/libxfs/xfs_rtalloc.c
+++ /dev/null
@@ -1,776 +0,0 @@
-/*
- * Copyright (c) 2000-2005 Silicon Graphics, 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>
-
-/*
- * Prototypes for internal functions.
- */
-
-
-STATIC int xfs_rtfind_back(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t,
- xfs_rtblock_t, xfs_rtblock_t *);
-STATIC int xfs_rtfind_forw(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t,
- xfs_rtblock_t, xfs_rtblock_t *);
-STATIC int xfs_rtmodify_range(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t,
- xfs_extlen_t, int);
-STATIC int xfs_rtmodify_summary(xfs_mount_t *, xfs_trans_t *, int,
- xfs_rtblock_t, int, xfs_buf_t **, xfs_fsblock_t *);
-
-/*
- * Internal functions.
- */
-
-/*
- * Get a buffer for the bitmap or summary file block specified.
- * The buffer is returned read and locked.
- */
-STATIC int /* error */
-xfs_rtbuf_get(
- xfs_mount_t *mp, /* file system mount structure */
- xfs_trans_t *tp, /* transaction pointer */
- xfs_rtblock_t block, /* block number in bitmap or summary */
- int issum, /* is summary not bitmap */
- xfs_buf_t **bpp) /* output: buffer for the block */
-{
- xfs_buf_t *bp; /* block buffer, result */
- xfs_inode_t *ip; /* bitmap or summary inode */
- xfs_bmbt_irec_t map;
- int nmap = 1;
- int error; /* error value */
-
- ip = issum ? mp->m_rsumip : mp->m_rbmip;
-
- error = xfs_bmapi_read(ip, block, 1, &map, &nmap, XFS_DATA_FORK);
- if (error)
- return error;
-
- ASSERT(map.br_startblock != NULLFSBLOCK);
- error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
- XFS_FSB_TO_DADDR(mp, map.br_startblock),
- mp->m_bsize, 0, &bp, NULL);
- if (error)
- return error;
- ASSERT(!xfs_buf_geterror(bp));
- *bpp = bp;
- return 0;
-}
-
-/*
- * Searching backward from start to limit, find the first block whose
- * allocated/free state is different from start's.
- */
-STATIC int /* error */
-xfs_rtfind_back(
- xfs_mount_t *mp, /* file system mount point */
- xfs_trans_t *tp, /* transaction pointer */
- xfs_rtblock_t start, /* starting block to look at */
- xfs_rtblock_t limit, /* last block to look at */
- xfs_rtblock_t *rtblock) /* out: start block found */
-{
- xfs_rtword_t *b; /* current word in buffer */
- int bit; /* bit number in the word */
- xfs_rtblock_t block; /* bitmap block number */
- xfs_buf_t *bp; /* buf for the block */
- xfs_rtword_t *bufp; /* starting word in buffer */
- int error; /* error value */
- xfs_rtblock_t firstbit; /* first useful bit in the word */
- xfs_rtblock_t i; /* current bit number rel. to start */
- xfs_rtblock_t len; /* length of inspected area */
- xfs_rtword_t mask; /* mask of relevant bits for value */
- xfs_rtword_t want; /* mask for "good" values */
- xfs_rtword_t wdiff; /* difference from wanted value */
- int word; /* word number in the buffer */
-
- /*
- * Compute and read in starting bitmap block for starting block.
- */
- block = XFS_BITTOBLOCK(mp, start);
- error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
- if (error) {
- return error;
- }
- bufp = bp->b_addr;
- /*
- * Get the first word's index & point to it.
- */
- word = XFS_BITTOWORD(mp, start);
- b = &bufp[word];
- bit = (int)(start & (XFS_NBWORD - 1));
- len = start - limit + 1;
- /*
- * Compute match value, based on the bit at start: if 1 (free)
- * then all-ones, else all-zeroes.
- */
- want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
- /*
- * If the starting position is not word-aligned, deal with the
- * partial word.
- */
- if (bit < XFS_NBWORD - 1) {
- /*
- * Calculate first (leftmost) bit number to look at,
- * and mask for all the relevant bits in this word.
- */
- firstbit = XFS_RTMAX((xfs_srtblock_t)(bit - len + 1), 0);
- mask = (((xfs_rtword_t)1 << (bit - firstbit + 1)) - 1) <<
- firstbit;
- /*
- * Calculate the difference between the value there
- * and what we're looking for.
- */
- if ((wdiff = (*b ^ want) & mask)) {
- /*
- * Different. Mark where we are and return.
- */
- xfs_trans_brelse(tp, bp);
- i = bit - XFS_RTHIBIT(wdiff);
- *rtblock = start - i + 1;
- return 0;
- }
- i = bit - firstbit + 1;
- /*
- * Go on to previous block if that's where the previous word is
- * and we need the previous word.
- */
- if (--word == -1 && i < len) {
- /*
- * If done with this block, get the previous one.
- */
- xfs_trans_brelse(tp, bp);
- error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
- if (error) {
- return error;
- }
- bufp = bp->b_addr;
- word = XFS_BLOCKWMASK(mp);
- b = &bufp[word];
- } else {
- /*
- * Go on to the previous word in the buffer.
- */
- b--;
- }
- } else {
- /*
- * Starting on a word boundary, no partial word.
- */
- i = 0;
- }
- /*
- * Loop over whole words in buffers. When we use up one buffer
- * we move on to the previous one.
- */
- while (len - i >= XFS_NBWORD) {
- /*
- * Compute difference between actual and desired value.
- */
- if ((wdiff = *b ^ want)) {
- /*
- * Different, mark where we are and return.
- */
- xfs_trans_brelse(tp, bp);
- i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
- *rtblock = start - i + 1;
- return 0;
- }
- i += XFS_NBWORD;
- /*
- * Go on to previous block if that's where the previous word is
- * and we need the previous word.
- */
- if (--word == -1 && i < len) {
- /*
- * If done with this block, get the previous one.
- */
- xfs_trans_brelse(tp, bp);
- error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
- if (error) {
- return error;
- }
- bufp = bp->b_addr;
- word = XFS_BLOCKWMASK(mp);
- b = &bufp[word];
- } else {
- /*
- * Go on to the previous word in the buffer.
- */
- b--;
- }
- }
- /*
- * If not ending on a word boundary, deal with the last
- * (partial) word.
- */
- if (len - i) {
- /*
- * Calculate first (leftmost) bit number to look at,
- * and mask for all the relevant bits in this word.
- */
- firstbit = XFS_NBWORD - (len - i);
- mask = (((xfs_rtword_t)1 << (len - i)) - 1) << firstbit;
- /*
- * Compute difference between actual and desired value.
- */
- if ((wdiff = (*b ^ want) & mask)) {
- /*
- * Different, mark where we are and return.
- */
- xfs_trans_brelse(tp, bp);
- i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
- *rtblock = start - i + 1;
- return 0;
- } else
- i = len;
- }
- /*
- * No match, return that we scanned the whole area.
- */
- xfs_trans_brelse(tp, bp);
- *rtblock = start - i + 1;
- return 0;
-}
-
-/*
- * Searching forward from start to limit, find the first block whose
- * allocated/free state is different from start's.
- */
-STATIC int /* error */
-xfs_rtfind_forw(
- xfs_mount_t *mp, /* file system mount point */
- xfs_trans_t *tp, /* transaction pointer */
- xfs_rtblock_t start, /* starting block to look at */
- xfs_rtblock_t limit, /* last block to look at */
- xfs_rtblock_t *rtblock) /* out: start block found */
-{
- xfs_rtword_t *b; /* current word in buffer */
- int bit; /* bit number in the word */
- xfs_rtblock_t block; /* bitmap block number */
- xfs_buf_t *bp; /* buf for the block */
- xfs_rtword_t *bufp; /* starting word in buffer */
- int error; /* error value */
- xfs_rtblock_t i; /* current bit number rel. to start */
- xfs_rtblock_t lastbit; /* last useful bit in the word */
- xfs_rtblock_t len; /* length of inspected area */
- xfs_rtword_t mask; /* mask of relevant bits for value */
- xfs_rtword_t want; /* mask for "good" values */
- xfs_rtword_t wdiff; /* difference from wanted value */
- int word; /* word number in the buffer */
-
- /*
- * Compute and read in starting bitmap block for starting block.
- */
- block = XFS_BITTOBLOCK(mp, start);
- error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
- if (error) {
- return error;
- }
- bufp = bp->b_addr;
- /*
- * Get the first word's index & point to it.
- */
- word = XFS_BITTOWORD(mp, start);
- b = &bufp[word];
- bit = (int)(start & (XFS_NBWORD - 1));
- len = limit - start + 1;
- /*
- * Compute match value, based on the bit at start: if 1 (free)
- * then all-ones, else all-zeroes.
- */
- want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
- /*
- * If the starting position is not word-aligned, deal with the
- * partial word.
- */
- if (bit) {
- /*
- * Calculate last (rightmost) bit number to look at,
- * and mask for all the relevant bits in this word.
- */
- lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
- mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
- /*
- * Calculate the difference between the value there
- * and what we're looking for.
- */
- if ((wdiff = (*b ^ want) & mask)) {
- /*
- * Different. Mark where we are and return.
- */
- xfs_trans_brelse(tp, bp);
- i = XFS_RTLOBIT(wdiff) - bit;
- *rtblock = start + i - 1;
- return 0;
- }
- i = lastbit - bit;
- /*
- * Go on to next block if that's where the next word is
- * and we need the next word.
- */
- if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
- /*
- * If done with this block, get the previous one.
- */
- xfs_trans_brelse(tp, bp);
- error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
- if (error) {
- return error;
- }
- b = bufp = bp->b_addr;
- word = 0;
- } else {
- /*
- * Go on to the previous word in the buffer.
- */
- b++;
- }
- } else {
- /*
- * Starting on a word boundary, no partial word.
- */
- i = 0;
- }
- /*
- * Loop over whole words in buffers. When we use up one buffer
- * we move on to the next one.
- */
- while (len - i >= XFS_NBWORD) {
- /*
- * Compute difference between actual and desired value.
- */
- if ((wdiff = *b ^ want)) {
- /*
- * Different, mark where we are and return.
- */
- xfs_trans_brelse(tp, bp);
- i += XFS_RTLOBIT(wdiff);
- *rtblock = start + i - 1;
- return 0;
- }
- i += XFS_NBWORD;
- /*
- * Go on to next block if that's where the next word is
- * and we need the next word.
- */
- if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
- /*
- * If done with this block, get the next one.
- */
- xfs_trans_brelse(tp, bp);
- error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
- if (error) {
- return error;
- }
- b = bufp = bp->b_addr;
- word = 0;
- } else {
- /*
- * Go on to the next word in the buffer.
- */
- b++;
- }
- }
- /*
- * If not ending on a word boundary, deal with the last
- * (partial) word.
- */
- if ((lastbit = len - i)) {
- /*
- * Calculate mask for all the relevant bits in this word.
- */
- mask = ((xfs_rtword_t)1 << lastbit) - 1;
- /*
- * Compute difference between actual and desired value.
- */
- if ((wdiff = (*b ^ want) & mask)) {
- /*
- * Different, mark where we are and return.
- */
- xfs_trans_brelse(tp, bp);
- i += XFS_RTLOBIT(wdiff);
- *rtblock = start + i - 1;
- return 0;
- } else
- i = len;
- }
- /*
- * No match, return that we scanned the whole area.
- */
- xfs_trans_brelse(tp, bp);
- *rtblock = start + i - 1;
- return 0;
-}
-
-/*
- * Mark an extent specified by start and len freed.
- * Updates all the summary information as well as the bitmap.
- */
-STATIC int /* error */
-xfs_rtfree_range(
- xfs_mount_t *mp, /* file system mount point */
- xfs_trans_t *tp, /* transaction pointer */
- xfs_rtblock_t start, /* starting block to free */
- xfs_extlen_t len, /* length to free */
- xfs_buf_t **rbpp, /* in/out: summary block buffer */
- xfs_fsblock_t *rsb) /* in/out: summary block number */
-{
- xfs_rtblock_t end; /* end of the freed extent */
- int error; /* error value */
- xfs_rtblock_t postblock = 0; /* first block freed > end */
- xfs_rtblock_t preblock = 0; /* first block freed < start */
-
- end = start + len - 1;
- /*
- * Modify the bitmap to mark this extent freed.
- */
- error = xfs_rtmodify_range(mp, tp, start, len, 1);
- if (error) {
- return error;
- }
- /*
- * Assume we're freeing out of the middle of an allocated extent.
- * We need to find the beginning and end of the extent so we can
- * properly update the summary.
- */
- error = xfs_rtfind_back(mp, tp, start, 0, &preblock);
- if (error) {
- return error;
- }
- /*
- * Find the next allocated block (end of allocated extent).
- */
- error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1,
- &postblock);
- if (error)
- return error;
- /*
- * If there are blocks not being freed at the front of the
- * old extent, add summary data for them to be allocated.
- */
- if (preblock < start) {
- error = xfs_rtmodify_summary(mp, tp,
- XFS_RTBLOCKLOG(start - preblock),
- XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb);
- if (error) {
- return error;
- }
- }
- /*
- * If there are blocks not being freed at the end of the
- * old extent, add summary data for them to be allocated.
- */
- if (postblock > end) {
- error = xfs_rtmodify_summary(mp, tp,
- XFS_RTBLOCKLOG(postblock - end),
- XFS_BITTOBLOCK(mp, end + 1), -1, rbpp, rsb);
- if (error) {
- return error;
- }
- }
- /*
- * Increment the summary information corresponding to the entire
- * (new) free extent.
- */
- error = xfs_rtmodify_summary(mp, tp,
- XFS_RTBLOCKLOG(postblock + 1 - preblock),
- XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb);
- return error;
-}
-
-/*
- * Set the given range of bitmap bits to the given value.
- * Do whatever I/O and logging is required.
- */
-STATIC int /* error */
-xfs_rtmodify_range(
- xfs_mount_t *mp, /* file system mount point */
- xfs_trans_t *tp, /* transaction pointer */
- xfs_rtblock_t start, /* starting block to modify */
- xfs_extlen_t len, /* length of extent to modify */
- int val) /* 1 for free, 0 for allocated */
-{
- xfs_rtword_t *b; /* current word in buffer */
- int bit; /* bit number in the word */
- xfs_rtblock_t block; /* bitmap block number */
- xfs_buf_t *bp; /* buf for the block */
- xfs_rtword_t *bufp; /* starting word in buffer */
- int error; /* error value */
- xfs_rtword_t *first; /* first used word in the buffer */
- int i; /* current bit number rel. to start */
- int lastbit; /* last useful bit in word */
- xfs_rtword_t mask; /* mask o frelevant bits for value */
- int word; /* word number in the buffer */
-
- /*
- * Compute starting bitmap block number.
- */
- block = XFS_BITTOBLOCK(mp, start);
- /*
- * Read the bitmap block, and point to its data.
- */
- error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
- if (error) {
- return error;
- }
- bufp = bp->b_addr;
- /*
- * Compute the starting word's address, and starting bit.
- */
- word = XFS_BITTOWORD(mp, start);
- first = b = &bufp[word];
- bit = (int)(start & (XFS_NBWORD - 1));
- /*
- * 0 (allocated) => all zeroes; 1 (free) => all ones.
- */
- val = -val;
- /*
- * If not starting on a word boundary, deal with the first
- * (partial) word.
- */
- if (bit) {
- /*
- * Compute first bit not changed and mask of relevant bits.
- */
- lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
- mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
- /*
- * Set/clear the active bits.
- */
- if (val)
- *b |= mask;
- else
- *b &= ~mask;
- i = lastbit - bit;
- /*
- * Go on to the next block if that's where the next word is
- * and we need the next word.
- */
- if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
- /*
- * Log the changed part of this block.
- * Get the next one.
- */
- xfs_trans_log_buf(tp, bp,
- (uint)((char *)first - (char *)bufp),
- (uint)((char *)b - (char *)bufp));
- error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
- if (error) {
- return error;
- }
- first = b = bufp = bp->b_addr;
- word = 0;
- } else {
- /*
- * Go on to the next word in the buffer
- */
- b++;
- }
- } else {
- /*
- * Starting on a word boundary, no partial word.
- */
- i = 0;
- }
- /*
- * Loop over whole words in buffers. When we use up one buffer
- * we move on to the next one.
- */
- while (len - i >= XFS_NBWORD) {
- /*
- * Set the word value correctly.
- */
- *b = val;
- i += XFS_NBWORD;
- /*
- * Go on to the next block if that's where the next word is
- * and we need the next word.
- */
- if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
- /*
- * Log the changed part of this block.
- * Get the next one.
- */
- xfs_trans_log_buf(tp, bp,
- (uint)((char *)first - (char *)bufp),
- (uint)((char *)b - (char *)bufp));
- error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
- if (error) {
- return error;
- }
- first = b = bufp = bp->b_addr;
- word = 0;
- } else {
- /*
- * Go on to the next word in the buffer
- */
- b++;
- }
- }
- /*
- * If not ending on a word boundary, deal with the last
- * (partial) word.
- */
- if ((lastbit = len - i)) {
- /*
- * Compute a mask of relevant bits.
- */
- bit = 0;
- mask = ((xfs_rtword_t)1 << lastbit) - 1;
- /*
- * Set/clear the active bits.
- */
- if (val)
- *b |= mask;
- else
- *b &= ~mask;
- b++;
- }
- /*
- * Log any remaining changed bytes.
- */
- if (b > first)
- xfs_trans_log_buf(tp, bp, (uint)((char *)first - (char *)bufp),
- (uint)((char *)b - (char *)bufp - 1));
- return 0;
-}
-
-/*
- * Read and modify the summary information for a given extent size,
- * bitmap block combination.
- * Keeps track of a current summary block, so we don't keep reading
- * it from the buffer cache.
- */
-STATIC int /* error */
-xfs_rtmodify_summary(
- xfs_mount_t *mp, /* file system mount point */
- xfs_trans_t *tp, /* transaction pointer */
- int log, /* log2 of extent size */
- xfs_rtblock_t bbno, /* bitmap block number */
- int delta, /* change to make to summary info */
- xfs_buf_t **rbpp, /* in/out: summary block buffer */
- xfs_fsblock_t *rsb) /* in/out: summary block number */
-{
- xfs_buf_t *bp; /* buffer for the summary block */
- int error; /* error value */
- xfs_fsblock_t sb; /* summary fsblock */
- int so; /* index into the summary file */
- xfs_suminfo_t *sp; /* pointer to returned data */
-
- /*
- * Compute entry number in the summary file.
- */
- so = XFS_SUMOFFS(mp, log, bbno);
- /*
- * Compute the block number in the summary file.
- */
- sb = XFS_SUMOFFSTOBLOCK(mp, so);
- /*
- * If we have an old buffer, and the block number matches, use that.
- */
- if (rbpp && *rbpp && *rsb == sb)
- bp = *rbpp;
- /*
- * Otherwise we have to get the buffer.
- */
- else {
- /*
- * If there was an old one, get rid of it first.
- */
- if (rbpp && *rbpp)
- xfs_trans_brelse(tp, *rbpp);
- error = xfs_rtbuf_get(mp, tp, sb, 1, &bp);
- if (error) {
- return error;
- }
- /*
- * Remember this buffer and block for the next call.
- */
- if (rbpp) {
- *rbpp = bp;
- *rsb = sb;
- }
- }
- /*
- * Point to the summary information, modify and log it.
- */
- sp = XFS_SUMPTR(mp, bp, so);
- *sp += delta;
- xfs_trans_log_buf(tp, bp, (uint)((char *)sp - (char *)bp->b_addr),
- (uint)((char *)sp - (char *)bp->b_addr + sizeof(*sp) - 1));
- return 0;
-}
-
-/*
- * Free an extent in the realtime subvolume. Length is expressed in
- * realtime extents, as is the block number.
- */
-int /* error */
-xfs_rtfree_extent(
- xfs_trans_t *tp, /* transaction pointer */
- xfs_rtblock_t bno, /* starting block number to free */
- xfs_extlen_t len) /* length of extent freed */
-{
- int error; /* error value */
- xfs_mount_t *mp; /* file system mount structure */
- xfs_fsblock_t sb; /* summary file block number */
- xfs_buf_t *sumbp; /* summary file block buffer */
-
- mp = tp->t_mountp;
-
- ASSERT(mp->m_rbmip->i_itemp != NULL);
- ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
-
-#ifdef DEBUG
- /*
- * Check to see that this whole range is currently allocated.
- */
- {
- int stat; /* result from checking range */
-
- error = xfs_rtcheck_alloc_range(mp, tp, bno, len, &stat);
- if (error) {
- return error;
- }
- ASSERT(stat);
- }
-#endif
- sumbp = NULL;
- /*
- * Free the range of realtime blocks.
- */
- error = xfs_rtfree_range(mp, tp, bno, len, &sumbp, &sb);
- if (error) {
- return error;
- }
- /*
- * Mark more blocks free in the superblock.
- */
- xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS, (long)len);
- /*
- * If we've now freed all the blocks, reset the file sequence
- * number to 0.
- */
- if (tp->t_frextents_delta + mp->m_sb.sb_frextents ==
- mp->m_sb.sb_rextents) {
- if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM))
- mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM;
- *(__uint64_t *)&mp->m_rbmip->i_d.di_atime = 0;
- xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
- }
- return 0;
-}
diff --git a/libxfs/xfs_rtbitmap.c b/libxfs/xfs_rtbitmap.c
new file mode 100644
index 0000000..1d2334e
--- /dev/null
+++ b/libxfs/xfs_rtbitmap.c
@@ -0,0 +1,951 @@
+/*
+ * Copyright (c) 2000-2005 Silicon Graphics, 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"
+
+/*
+ * Realtime allocator bitmap functions shared with userspace.
+ */
+
+/*
+ * Get a buffer for the bitmap or summary file block specified.
+ * The buffer is returned read and locked.
+ */
+int
+xfs_rtbuf_get(
+ xfs_mount_t *mp, /* file system mount structure */
+ xfs_trans_t *tp, /* transaction pointer */
+ xfs_rtblock_t block, /* block number in bitmap or summary */
+ int issum, /* is summary not bitmap */
+ xfs_buf_t **bpp) /* output: buffer for the block */
+{
+ xfs_buf_t *bp; /* block buffer, result */
+ xfs_inode_t *ip; /* bitmap or summary inode */
+ xfs_bmbt_irec_t map;
+ int nmap = 1;
+ int error; /* error value */
+
+ ip = issum ? mp->m_rsumip : mp->m_rbmip;
+
+ error = xfs_bmapi_read(ip, block, 1, &map, &nmap, XFS_DATA_FORK);
+ if (error)
+ return error;
+
+ ASSERT(map.br_startblock != NULLFSBLOCK);
+ error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
+ XFS_FSB_TO_DADDR(mp, map.br_startblock),
+ mp->m_bsize, 0, &bp, NULL);
+ if (error)
+ return error;
+ ASSERT(!xfs_buf_geterror(bp));
+ *bpp = bp;
+ return 0;
+}
+
+/*
+ * Searching backward from start to limit, find the first block whose
+ * allocated/free state is different from start's.
+ */
+int
+xfs_rtfind_back(
+ xfs_mount_t *mp, /* file system mount point */
+ xfs_trans_t *tp, /* transaction pointer */
+ xfs_rtblock_t start, /* starting block to look at */
+ xfs_rtblock_t limit, /* last block to look at */
+ xfs_rtblock_t *rtblock) /* out: start block found */
+{
+ xfs_rtword_t *b; /* current word in buffer */
+ int bit; /* bit number in the word */
+ xfs_rtblock_t block; /* bitmap block number */
+ xfs_buf_t *bp; /* buf for the block */
+ xfs_rtword_t *bufp; /* starting word in buffer */
+ int error; /* error value */
+ xfs_rtblock_t firstbit; /* first useful bit in the word */
+ xfs_rtblock_t i; /* current bit number rel. to start */
+ xfs_rtblock_t len; /* length of inspected area */
+ xfs_rtword_t mask; /* mask of relevant bits for value */
+ xfs_rtword_t want; /* mask for "good" values */
+ xfs_rtword_t wdiff; /* difference from wanted value */
+ int word; /* word number in the buffer */
+
+ /*
+ * Compute and read in starting bitmap block for starting block.
+ */
+ block = XFS_BITTOBLOCK(mp, start);
+ error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
+ if (error) {
+ return error;
+ }
+ bufp = bp->b_addr;
+ /*
+ * Get the first word's index & point to it.
+ */
+ word = XFS_BITTOWORD(mp, start);
+ b = &bufp[word];
+ bit = (int)(start & (XFS_NBWORD - 1));
+ len = start - limit + 1;
+ /*
+ * Compute match value, based on the bit at start: if 1 (free)
+ * then all-ones, else all-zeroes.
+ */
+ want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
+ /*
+ * If the starting position is not word-aligned, deal with the
+ * partial word.
+ */
+ if (bit < XFS_NBWORD - 1) {
+ /*
+ * Calculate first (leftmost) bit number to look at,
+ * and mask for all the relevant bits in this word.
+ */
+ firstbit = XFS_RTMAX((xfs_srtblock_t)(bit - len + 1), 0);
+ mask = (((xfs_rtword_t)1 << (bit - firstbit + 1)) - 1) <<
+ firstbit;
+ /*
+ * Calculate the difference between the value there
+ * and what we're looking for.
+ */
+ if ((wdiff = (*b ^ want) & mask)) {
+ /*
+ * Different. Mark where we are and return.
+ */
+ xfs_trans_brelse(tp, bp);
+ i = bit - XFS_RTHIBIT(wdiff);
+ *rtblock = start - i + 1;
+ return 0;
+ }
+ i = bit - firstbit + 1;
+ /*
+ * Go on to previous block if that's where the previous word is
+ * and we need the previous word.
+ */
+ if (--word == -1 && i < len) {
+ /*
+ * If done with this block, get the previous one.
+ */
+ xfs_trans_brelse(tp, bp);
+ error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
+ if (error) {
+ return error;
+ }
+ bufp = bp->b_addr;
+ word = XFS_BLOCKWMASK(mp);
+ b = &bufp[word];
+ } else {
+ /*
+ * Go on to the previous word in the buffer.
+ */
+ b--;
+ }
+ } else {
+ /*
+ * Starting on a word boundary, no partial word.
+ */
+ i = 0;
+ }
+ /*
+ * Loop over whole words in buffers. When we use up one buffer
+ * we move on to the previous one.
+ */
+ while (len - i >= XFS_NBWORD) {
+ /*
+ * Compute difference between actual and desired value.
+ */
+ if ((wdiff = *b ^ want)) {
+ /*
+ * Different, mark where we are and return.
+ */
+ xfs_trans_brelse(tp, bp);
+ i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
+ *rtblock = start - i + 1;
+ return 0;
+ }
+ i += XFS_NBWORD;
+ /*
+ * Go on to previous block if that's where the previous word is
+ * and we need the previous word.
+ */
+ if (--word == -1 && i < len) {
+ /*
+ * If done with this block, get the previous one.
+ */
+ xfs_trans_brelse(tp, bp);
+ error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
+ if (error) {
+ return error;
+ }
+ bufp = bp->b_addr;
+ word = XFS_BLOCKWMASK(mp);
+ b = &bufp[word];
+ } else {
+ /*
+ * Go on to the previous word in the buffer.
+ */
+ b--;
+ }
+ }
+ /*
+ * If not ending on a word boundary, deal with the last
+ * (partial) word.
+ */
+ if (len - i) {
+ /*
+ * Calculate first (leftmost) bit number to look at,
+ * and mask for all the relevant bits in this word.
+ */
+ firstbit = XFS_NBWORD - (len - i);
+ mask = (((xfs_rtword_t)1 << (len - i)) - 1) << firstbit;
+ /*
+ * Compute difference between actual and desired value.
+ */
+ if ((wdiff = (*b ^ want) & mask)) {
+ /*
+ * Different, mark where we are and return.
+ */
+ xfs_trans_brelse(tp, bp);
+ i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
+ *rtblock = start - i + 1;
+ return 0;
+ } else
+ i = len;
+ }
+ /*
+ * No match, return that we scanned the whole area.
+ */
+ xfs_trans_brelse(tp, bp);
+ *rtblock = start - i + 1;
+ return 0;
+}
+
+/*
+ * Searching forward from start to limit, find the first block whose
+ * allocated/free state is different from start's.
+ */
+int
+xfs_rtfind_forw(
+ xfs_mount_t *mp, /* file system mount point */
+ xfs_trans_t *tp, /* transaction pointer */
+ xfs_rtblock_t start, /* starting block to look at */
+ xfs_rtblock_t limit, /* last block to look at */
+ xfs_rtblock_t *rtblock) /* out: start block found */
+{
+ xfs_rtword_t *b; /* current word in buffer */
+ int bit; /* bit number in the word */
+ xfs_rtblock_t block; /* bitmap block number */
+ xfs_buf_t *bp; /* buf for the block */
+ xfs_rtword_t *bufp; /* starting word in buffer */
+ int error; /* error value */
+ xfs_rtblock_t i; /* current bit number rel. to start */
+ xfs_rtblock_t lastbit; /* last useful bit in the word */
+ xfs_rtblock_t len; /* length of inspected area */
+ xfs_rtword_t mask; /* mask of relevant bits for value */
+ xfs_rtword_t want; /* mask for "good" values */
+ xfs_rtword_t wdiff; /* difference from wanted value */
+ int word; /* word number in the buffer */
+
+ /*
+ * Compute and read in starting bitmap block for starting block.
+ */
+ block = XFS_BITTOBLOCK(mp, start);
+ error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
+ if (error) {
+ return error;
+ }
+ bufp = bp->b_addr;
+ /*
+ * Get the first word's index & point to it.
+ */
+ word = XFS_BITTOWORD(mp, start);
+ b = &bufp[word];
+ bit = (int)(start & (XFS_NBWORD - 1));
+ len = limit - start + 1;
+ /*
+ * Compute match value, based on the bit at start: if 1 (free)
+ * then all-ones, else all-zeroes.
+ */
+ want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
+ /*
+ * If the starting position is not word-aligned, deal with the
+ * partial word.
+ */
+ if (bit) {
+ /*
+ * Calculate last (rightmost) bit number to look at,
+ * and mask for all the relevant bits in this word.
+ */
+ lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
+ mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
+ /*
+ * Calculate the difference between the value there
+ * and what we're looking for.
+ */
+ if ((wdiff = (*b ^ want) & mask)) {
+ /*
+ * Different. Mark where we are and return.
+ */
+ xfs_trans_brelse(tp, bp);
+ i = XFS_RTLOBIT(wdiff) - bit;
+ *rtblock = start + i - 1;
+ return 0;
+ }
+ i = lastbit - bit;
+ /*
+ * Go on to next block if that's where the next word is
+ * and we need the next word.
+ */
+ if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
+ /*
+ * If done with this block, get the previous one.
+ */
+ xfs_trans_brelse(tp, bp);
+ error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
+ if (error) {
+ return error;
+ }
+ b = bufp = bp->b_addr;
+ word = 0;
+ } else {
+ /*
+ * Go on to the previous word in the buffer.
+ */
+ b++;
+ }
+ } else {
+ /*
+ * Starting on a word boundary, no partial word.
+ */
+ i = 0;
+ }
+ /*
+ * Loop over whole words in buffers. When we use up one buffer
+ * we move on to the next one.
+ */
+ while (len - i >= XFS_NBWORD) {
+ /*
+ * Compute difference between actual and desired value.
+ */
+ if ((wdiff = *b ^ want)) {
+ /*
+ * Different, mark where we are and return.
+ */
+ xfs_trans_brelse(tp, bp);
+ i += XFS_RTLOBIT(wdiff);
+ *rtblock = start + i - 1;
+ return 0;
+ }
+ i += XFS_NBWORD;
+ /*
+ * Go on to next block if that's where the next word is
+ * and we need the next word.
+ */
+ if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
+ /*
+ * If done with this block, get the next one.
+ */
+ xfs_trans_brelse(tp, bp);
+ error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
+ if (error) {
+ return error;
+ }
+ b = bufp = bp->b_addr;
+ word = 0;
+ } else {
+ /*
+ * Go on to the next word in the buffer.
+ */
+ b++;
+ }
+ }
+ /*
+ * If not ending on a word boundary, deal with the last
+ * (partial) word.
+ */
+ if ((lastbit = len - i)) {
+ /*
+ * Calculate mask for all the relevant bits in this word.
+ */
+ mask = ((xfs_rtword_t)1 << lastbit) - 1;
+ /*
+ * Compute difference between actual and desired value.
+ */
+ if ((wdiff = (*b ^ want) & mask)) {
+ /*
+ * Different, mark where we are and return.
+ */
+ xfs_trans_brelse(tp, bp);
+ i += XFS_RTLOBIT(wdiff);
+ *rtblock = start + i - 1;
+ return 0;
+ } else
+ i = len;
+ }
+ /*
+ * No match, return that we scanned the whole area.
+ */
+ xfs_trans_brelse(tp, bp);
+ *rtblock = start + i - 1;
+ return 0;
+}
+
+/*
+ * Read and modify the summary information for a given extent size,
+ * bitmap block combination.
+ * Keeps track of a current summary block, so we don't keep reading
+ * it from the buffer cache.
+ */
+int
+xfs_rtmodify_summary(
+ xfs_mount_t *mp, /* file system mount point */
+ xfs_trans_t *tp, /* transaction pointer */
+ int log, /* log2 of extent size */
+ xfs_rtblock_t bbno, /* bitmap block number */
+ int delta, /* change to make to summary info */
+ xfs_buf_t **rbpp, /* in/out: summary block buffer */
+ xfs_fsblock_t *rsb) /* in/out: summary block number */
+{
+ xfs_buf_t *bp; /* buffer for the summary block */
+ int error; /* error value */
+ xfs_fsblock_t sb; /* summary fsblock */
+ int so; /* index into the summary file */
+ xfs_suminfo_t *sp; /* pointer to returned data */
+
+ /*
+ * Compute entry number in the summary file.
+ */
+ so = XFS_SUMOFFS(mp, log, bbno);
+ /*
+ * Compute the block number in the summary file.
+ */
+ sb = XFS_SUMOFFSTOBLOCK(mp, so);
+ /*
+ * If we have an old buffer, and the block number matches, use that.
+ */
+ if (rbpp && *rbpp && *rsb == sb)
+ bp = *rbpp;
+ /*
+ * Otherwise we have to get the buffer.
+ */
+ else {
+ /*
+ * If there was an old one, get rid of it first.
+ */
+ if (rbpp && *rbpp)
+ xfs_trans_brelse(tp, *rbpp);
+ error = xfs_rtbuf_get(mp, tp, sb, 1, &bp);
+ if (error) {
+ return error;
+ }
+ /*
+ * Remember this buffer and block for the next call.
+ */
+ if (rbpp) {
+ *rbpp = bp;
+ *rsb = sb;
+ }
+ }
+ /*
+ * Point to the summary information, modify and log it.
+ */
+ sp = XFS_SUMPTR(mp, bp, so);
+ *sp += delta;
+ xfs_trans_log_buf(tp, bp, (uint)((char *)sp - (char *)bp->b_addr),
+ (uint)((char *)sp - (char *)bp->b_addr + sizeof(*sp) - 1));
+ return 0;
+}
+
+/*
+ * Set the given range of bitmap bits to the given value.
+ * Do whatever I/O and logging is required.
+ */
+int
+xfs_rtmodify_range(
+ xfs_mount_t *mp, /* file system mount point */
+ xfs_trans_t *tp, /* transaction pointer */
+ xfs_rtblock_t start, /* starting block to modify */
+ xfs_extlen_t len, /* length of extent to modify */
+ int val) /* 1 for free, 0 for allocated */
+{
+ xfs_rtword_t *b; /* current word in buffer */
+ int bit; /* bit number in the word */
+ xfs_rtblock_t block; /* bitmap block number */
+ xfs_buf_t *bp; /* buf for the block */
+ xfs_rtword_t *bufp; /* starting word in buffer */
+ int error; /* error value */
+ xfs_rtword_t *first; /* first used word in the buffer */
+ int i; /* current bit number rel. to start */
+ int lastbit; /* last useful bit in word */
+ xfs_rtword_t mask; /* mask o frelevant bits for value */
+ int word; /* word number in the buffer */
+
+ /*
+ * Compute starting bitmap block number.
+ */
+ block = XFS_BITTOBLOCK(mp, start);
+ /*
+ * Read the bitmap block, and point to its data.
+ */
+ error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
+ if (error) {
+ return error;
+ }
+ bufp = bp->b_addr;
+ /*
+ * Compute the starting word's address, and starting bit.
+ */
+ word = XFS_BITTOWORD(mp, start);
+ first = b = &bufp[word];
+ bit = (int)(start & (XFS_NBWORD - 1));
+ /*
+ * 0 (allocated) => all zeroes; 1 (free) => all ones.
+ */
+ val = -val;
+ /*
+ * If not starting on a word boundary, deal with the first
+ * (partial) word.
+ */
+ if (bit) {
+ /*
+ * Compute first bit not changed and mask of relevant bits.
+ */
+ lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
+ mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
+ /*
+ * Set/clear the active bits.
+ */
+ if (val)
+ *b |= mask;
+ else
+ *b &= ~mask;
+ i = lastbit - bit;
+ /*
+ * Go on to the next block if that's where the next word is
+ * and we need the next word.
+ */
+ if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
+ /*
+ * Log the changed part of this block.
+ * Get the next one.
+ */
+ xfs_trans_log_buf(tp, bp,
+ (uint)((char *)first - (char *)bufp),
+ (uint)((char *)b - (char *)bufp));
+ error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
+ if (error) {
+ return error;
+ }
+ first = b = bufp = bp->b_addr;
+ word = 0;
+ } else {
+ /*
+ * Go on to the next word in the buffer
+ */
+ b++;
+ }
+ } else {
+ /*
+ * Starting on a word boundary, no partial word.
+ */
+ i = 0;
+ }
+ /*
+ * Loop over whole words in buffers. When we use up one buffer
+ * we move on to the next one.
+ */
+ while (len - i >= XFS_NBWORD) {
+ /*
+ * Set the word value correctly.
+ */
+ *b = val;
+ i += XFS_NBWORD;
+ /*
+ * Go on to the next block if that's where the next word is
+ * and we need the next word.
+ */
+ if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
+ /*
+ * Log the changed part of this block.
+ * Get the next one.
+ */
+ xfs_trans_log_buf(tp, bp,
+ (uint)((char *)first - (char *)bufp),
+ (uint)((char *)b - (char *)bufp));
+ error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
+ if (error) {
+ return error;
+ }
+ first = b = bufp = bp->b_addr;
+ word = 0;
+ } else {
+ /*
+ * Go on to the next word in the buffer
+ */
+ b++;
+ }
+ }
+ /*
+ * If not ending on a word boundary, deal with the last
+ * (partial) word.
+ */
+ if ((lastbit = len - i)) {
+ /*
+ * Compute a mask of relevant bits.
+ */
+ bit = 0;
+ mask = ((xfs_rtword_t)1 << lastbit) - 1;
+ /*
+ * Set/clear the active bits.
+ */
+ if (val)
+ *b |= mask;
+ else
+ *b &= ~mask;
+ b++;
+ }
+ /*
+ * Log any remaining changed bytes.
+ */
+ if (b > first)
+ xfs_trans_log_buf(tp, bp, (uint)((char *)first - (char *)bufp),
+ (uint)((char *)b - (char *)bufp - 1));
+ return 0;
+}
+
+/*
+ * Mark an extent specified by start and len freed.
+ * Updates all the summary information as well as the bitmap.
+ */
+int
+xfs_rtfree_range(
+ xfs_mount_t *mp, /* file system mount point */
+ xfs_trans_t *tp, /* transaction pointer */
+ xfs_rtblock_t start, /* starting block to free */
+ xfs_extlen_t len, /* length to free */
+ xfs_buf_t **rbpp, /* in/out: summary block buffer */
+ xfs_fsblock_t *rsb) /* in/out: summary block number */
+{
+ xfs_rtblock_t end; /* end of the freed extent */
+ int error; /* error value */
+ xfs_rtblock_t postblock; /* first block freed > end */
+ xfs_rtblock_t preblock; /* first block freed < start */
+
+ end = start + len - 1;
+ /*
+ * Modify the bitmap to mark this extent freed.
+ */
+ error = xfs_rtmodify_range(mp, tp, start, len, 1);
+ if (error) {
+ return error;
+ }
+ /*
+ * Assume we're freeing out of the middle of an allocated extent.
+ * We need to find the beginning and end of the extent so we can
+ * properly update the summary.
+ */
+ error = xfs_rtfind_back(mp, tp, start, 0, &preblock);
+ if (error) {
+ return error;
+ }
+ /*
+ * Find the next allocated block (end of allocated extent).
+ */
+ error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1,
+ &postblock);
+ if (error)
+ return error;
+ /*
+ * If there are blocks not being freed at the front of the
+ * old extent, add summary data for them to be allocated.
+ */
+ if (preblock < start) {
+ error = xfs_rtmodify_summary(mp, tp,
+ XFS_RTBLOCKLOG(start - preblock),
+ XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb);
+ if (error) {
+ return error;
+ }
+ }
+ /*
+ * If there are blocks not being freed at the end of the
+ * old extent, add summary data for them to be allocated.
+ */
+ if (postblock > end) {
+ error = xfs_rtmodify_summary(mp, tp,
+ XFS_RTBLOCKLOG(postblock - end),
+ XFS_BITTOBLOCK(mp, end + 1), -1, rbpp, rsb);
+ if (error) {
+ return error;
+ }
+ }
+ /*
+ * Increment the summary information corresponding to the entire
+ * (new) free extent.
+ */
+ error = xfs_rtmodify_summary(mp, tp,
+ XFS_RTBLOCKLOG(postblock + 1 - preblock),
+ XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb);
+ return error;
+}
+
+/*
+ * Check that the given range is either all allocated (val = 0) or
+ * all free (val = 1).
+ */
+int
+xfs_rtcheck_range(
+ xfs_mount_t *mp, /* file system mount point */
+ xfs_trans_t *tp, /* transaction pointer */
+ xfs_rtblock_t start, /* starting block number of extent */
+ xfs_extlen_t len, /* length of extent */
+ int val, /* 1 for free, 0 for allocated */
+ xfs_rtblock_t *new, /* out: first block not matching */
+ int *stat) /* out: 1 for matches, 0 for not */
+{
+ xfs_rtword_t *b; /* current word in buffer */
+ int bit; /* bit number in the word */
+ xfs_rtblock_t block; /* bitmap block number */
+ xfs_buf_t *bp; /* buf for the block */
+ xfs_rtword_t *bufp; /* starting word in buffer */
+ int error; /* error value */
+ xfs_rtblock_t i; /* current bit number rel. to start */
+ xfs_rtblock_t lastbit; /* last useful bit in word */
+ xfs_rtword_t mask; /* mask of relevant bits for value */
+ xfs_rtword_t wdiff; /* difference from wanted value */
+ int word; /* word number in the buffer */
+
+ /*
+ * Compute starting bitmap block number
+ */
+ block = XFS_BITTOBLOCK(mp, start);
+ /*
+ * Read the bitmap block.
+ */
+ error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
+ if (error) {
+ return error;
+ }
+ bufp = bp->b_addr;
+ /*
+ * Compute the starting word's address, and starting bit.
+ */
+ word = XFS_BITTOWORD(mp, start);
+ b = &bufp[word];
+ bit = (int)(start & (XFS_NBWORD - 1));
+ /*
+ * 0 (allocated) => all zero's; 1 (free) => all one's.
+ */
+ val = -val;
+ /*
+ * If not starting on a word boundary, deal with the first
+ * (partial) word.
+ */
+ if (bit) {
+ /*
+ * Compute first bit not examined.
+ */
+ lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
+ /*
+ * Mask of relevant bits.
+ */
+ mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
+ /*
+ * Compute difference between actual and desired value.
+ */
+ if ((wdiff = (*b ^ val) & mask)) {
+ /*
+ * Different, compute first wrong bit and return.
+ */
+ xfs_trans_brelse(tp, bp);
+ i = XFS_RTLOBIT(wdiff) - bit;
+ *new = start + i;
+ *stat = 0;
+ return 0;
+ }
+ i = lastbit - bit;
+ /*
+ * Go on to next block if that's where the next word is
+ * and we need the next word.
+ */
+ if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
+ /*
+ * If done with this block, get the next one.
+ */
+ xfs_trans_brelse(tp, bp);
+ error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
+ if (error) {
+ return error;
+ }
+ b = bufp = bp->b_addr;
+ word = 0;
+ } else {
+ /*
+ * Go on to the next word in the buffer.
+ */
+ b++;
+ }
+ } else {
+ /*
+ * Starting on a word boundary, no partial word.
+ */
+ i = 0;
+ }
+ /*
+ * Loop over whole words in buffers. When we use up one buffer
+ * we move on to the next one.
+ */
+ while (len - i >= XFS_NBWORD) {
+ /*
+ * Compute difference between actual and desired value.
+ */
+ if ((wdiff = *b ^ val)) {
+ /*
+ * Different, compute first wrong bit and return.
+ */
+ xfs_trans_brelse(tp, bp);
+ i += XFS_RTLOBIT(wdiff);
+ *new = start + i;
+ *stat = 0;
+ return 0;
+ }
+ i += XFS_NBWORD;
+ /*
+ * Go on to next block if that's where the next word is
+ * and we need the next word.
+ */
+ if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
+ /*
+ * If done with this block, get the next one.
+ */
+ xfs_trans_brelse(tp, bp);
+ error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
+ if (error) {
+ return error;
+ }
+ b = bufp = bp->b_addr;
+ word = 0;
+ } else {
+ /*
+ * Go on to the next word in the buffer.
+ */
+ b++;
+ }
+ }
+ /*
+ * If not ending on a word boundary, deal with the last
+ * (partial) word.
+ */
+ if ((lastbit = len - i)) {
+ /*
+ * Mask of relevant bits.
+ */
+ mask = ((xfs_rtword_t)1 << lastbit) - 1;
+ /*
+ * Compute difference between actual and desired value.
+ */
+ if ((wdiff = (*b ^ val) & mask)) {
+ /*
+ * Different, compute first wrong bit and return.
+ */
+ xfs_trans_brelse(tp, bp);
+ i += XFS_RTLOBIT(wdiff);
+ *new = start + i;
+ *stat = 0;
+ return 0;
+ } else
+ i = len;
+ }
+ /*
+ * Successful, return.
+ */
+ xfs_trans_brelse(tp, bp);
+ *new = start + i;
+ *stat = 1;
+ return 0;
+}
+
+#ifdef DEBUG
+/*
+ * Check that the given extent (block range) is allocated already.
+ */
+STATIC int /* error */
+xfs_rtcheck_alloc_range(
+ xfs_mount_t *mp, /* file system mount point */
+ xfs_trans_t *tp, /* transaction pointer */
+ xfs_rtblock_t bno, /* starting block number of extent */
+ xfs_extlen_t len) /* length of extent */
+{
+ xfs_rtblock_t new; /* dummy for xfs_rtcheck_range */
+ int stat;
+ int error;
+
+ error = xfs_rtcheck_range(mp, tp, bno, len, 0, &new, &stat);
+ if (error)
+ return error;
+ ASSERT(stat);
+ return 0;
+}
+#else
+#define xfs_rtcheck_alloc_range(m,t,b,l) (0)
+#endif
+/*
+ * Free an extent in the realtime subvolume. Length is expressed in
+ * realtime extents, as is the block number.
+ */
+int /* error */
+xfs_rtfree_extent(
+ xfs_trans_t *tp, /* transaction pointer */
+ xfs_rtblock_t bno, /* starting block number to free */
+ xfs_extlen_t len) /* length of extent freed */
+{
+ int error; /* error value */
+ xfs_mount_t *mp; /* file system mount structure */
+ xfs_fsblock_t sb; /* summary file block number */
+ xfs_buf_t *sumbp= NULL; /* summary file block buffer */
+
+ mp = tp->t_mountp;
+
+ ASSERT(mp->m_rbmip->i_itemp != NULL);
+ ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
+
+ error = xfs_rtcheck_alloc_range(mp, tp, bno, len);
+ if (error)
+ return error;
+
+ /*
+ * Free the range of realtime blocks.
+ */
+ error = xfs_rtfree_range(mp, tp, bno, len, &sumbp, &sb);
+ if (error) {
+ return error;
+ }
+ /*
+ * Mark more blocks free in the superblock.
+ */
+ xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS, (long)len);
+ /*
+ * If we've now freed all the blocks, reset the file sequence
+ * number to 0.
+ */
+ if (tp->t_frextents_delta + mp->m_sb.sb_frextents ==
+ mp->m_sb.sb_rextents) {
+ if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM))
+ mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM;
+ *(__uint64_t *)&mp->m_rbmip->i_d.di_atime = 0;
+ xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
+ }
+ return 0;
+}
+
--
1.8.3.2
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 15/32] libxfs: bring across inode buffer readahead verifier changes
[not found] <1380510944-8571-1-git-send-email-david@fromorbit.com>
` (13 preceding siblings ...)
2013-09-30 3:15 ` [PATCH 14/32] libxfs: xfs_rtalloc.c becomes xfs_rtbitmap.c Dave Chinner
@ 2013-09-30 3:15 ` Dave Chinner
2013-09-30 3:15 ` [PATCH 16/32] libxfs: Minor cleanup and bug fix sync Dave Chinner
` (16 subsequent siblings)
31 siblings, 0 replies; 56+ messages in thread
From: Dave Chinner @ 2013-09-30 3:15 UTC (permalink / raw)
To: xfs
From: Dave Chinner <dchinner@redhat.com>
These were made for log recovery readahead in the kernel, so are not
directly used in userspace. Hence bringing the change across is
simply to keep files in sync.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
libxfs/xfs_inode_buf.c | 41 ++++++++++++++++++++++++++++++++++++-----
1 file changed, 36 insertions(+), 5 deletions(-)
diff --git a/libxfs/xfs_inode_buf.c b/libxfs/xfs_inode_buf.c
index b096f77..67d5eb4 100644
--- a/libxfs/xfs_inode_buf.c
+++ b/libxfs/xfs_inode_buf.c
@@ -46,9 +46,22 @@ xfs_inobp_check(
}
#endif
+/*
+ * If we are doing readahead on an inode buffer, we might be in log recovery
+ * reading an inode allocation buffer that hasn't yet been replayed, and hence
+ * has not had the inode cores stamped into it. Hence for readahead, the buffer
+ * may be potentially invalid.
+ *
+ * If the readahead buffer is invalid, we don't want to mark it with an error,
+ * but we do want to clear the DONE status of the buffer so that a followup read
+ * will re-read it from disk. This will ensure that we don't get an unnecessary
+ * warnings during log recovery and we don't get unnecssary panics on debug
+ * kernels.
+ */
static void
xfs_inode_buf_verify(
- struct xfs_buf *bp)
+ struct xfs_buf *bp,
+ bool readahead)
{
struct xfs_mount *mp = bp->b_target->bt_mount;
int i;
@@ -69,6 +82,11 @@ xfs_inode_buf_verify(
if (unlikely(XFS_TEST_ERROR(!di_ok, mp,
XFS_ERRTAG_ITOBP_INOTOBP,
XFS_RANDOM_ITOBP_INOTOBP))) {
+ if (readahead) {
+ bp->b_flags &= ~XBF_DONE;
+ return;
+ }
+
xfs_buf_ioerror(bp, EFSCORRUPTED);
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_HIGH,
mp, dip);
@@ -87,14 +105,21 @@ static void
xfs_inode_buf_read_verify(
struct xfs_buf *bp)
{
- xfs_inode_buf_verify(bp);
+ xfs_inode_buf_verify(bp, false);
+}
+
+static void
+xfs_inode_buf_readahead_verify(
+ struct xfs_buf *bp)
+{
+ xfs_inode_buf_verify(bp, true);
}
static void
xfs_inode_buf_write_verify(
struct xfs_buf *bp)
{
- xfs_inode_buf_verify(bp);
+ xfs_inode_buf_verify(bp, false);
}
const struct xfs_buf_ops xfs_inode_buf_ops = {
@@ -102,6 +127,12 @@ const struct xfs_buf_ops xfs_inode_buf_ops = {
.verify_write = xfs_inode_buf_write_verify,
};
+const struct xfs_buf_ops xfs_inode_buf_ra_ops = {
+ .verify_read = xfs_inode_buf_readahead_verify,
+ .verify_write = xfs_inode_buf_write_verify,
+};
+
+
/*
* This routine is called to map an inode to the buffer containing the on-disk
* version of the inode. It returns a pointer to the buffer containing the
@@ -191,7 +222,7 @@ xfs_dinode_from_disk(
to->di_ino = be64_to_cpu(from->di_ino);
to->di_lsn = be64_to_cpu(from->di_lsn);
memcpy(to->di_pad2, from->di_pad2, sizeof(to->di_pad2));
- platform_uuid_copy(&to->di_uuid, &from->di_uuid);
+ uuid_copy(&to->di_uuid, &from->di_uuid);
}
}
@@ -237,7 +268,7 @@ xfs_dinode_to_disk(
to->di_ino = cpu_to_be64(from->di_ino);
to->di_lsn = cpu_to_be64(from->di_lsn);
memcpy(to->di_pad2, from->di_pad2, sizeof(to->di_pad2));
- platform_uuid_copy(&to->di_uuid, &from->di_uuid);
+ uuid_copy(&to->di_uuid, &from->di_uuid);
to->di_flushiter = 0;
} else {
to->di_flushiter = cpu_to_be16(from->di_flushiter);
--
1.8.3.2
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 16/32] libxfs: Minor cleanup and bug fix sync
[not found] <1380510944-8571-1-git-send-email-david@fromorbit.com>
` (14 preceding siblings ...)
2013-09-30 3:15 ` [PATCH 15/32] libxfs: bring across inode buffer readahead verifier changes Dave Chinner
@ 2013-09-30 3:15 ` Dave Chinner
2013-09-30 3:15 ` [PATCH 17/32] db: separate out straight buffer IO from map based IO Dave Chinner
` (15 subsequent siblings)
31 siblings, 0 replies; 56+ messages in thread
From: Dave Chinner @ 2013-09-30 3:15 UTC (permalink / raw)
To: xfs
From: Dave Chinner <dchinner@redhat.com>
These bring all the small single line comment, whitespace and minor
code differences into sync with the kernel code. Anything left at
this point is an intentional difference.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
include/xfs_fs.h | 4 ++--
include/xfs_quota_defs.h | 4 ++++
libxfs/xfs_attr_leaf.c | 4 +---
libxfs/xfs_bmap.c | 6 +++---
libxfs/xfs_bmap_btree.c | 2 +-
libxfs/xfs_dir2_leaf.c | 1 -
libxfs/xfs_dir2_node.c | 2 +-
libxfs/xfs_ialloc.c | 4 ++--
libxfs/xfs_inode_buf.c | 2 ++
libxfs/xfs_inode_fork.c | 5 +++--
libxfs/xfs_trans_resv.c | 2 +-
11 files changed, 20 insertions(+), 16 deletions(-)
diff --git a/include/xfs_fs.h b/include/xfs_fs.h
index 53e33c2..18272c7 100644
--- a/include/xfs_fs.h
+++ b/include/xfs_fs.h
@@ -357,7 +357,7 @@ typedef struct xfs_error_injection {
* Speculative preallocation trimming.
*/
#define XFS_EOFBLOCKS_VERSION 1
-struct xfs_eofblocks {
+struct xfs_fs_eofblocks {
__u32 eof_version;
__u32 eof_flags;
uid_t eof_uid;
@@ -515,7 +515,7 @@ typedef struct xfs_swapext
/* XFS_IOC_GETBIOSIZE ---- deprecated 47 */
#define XFS_IOC_GETBMAPX _IOWR('X', 56, struct getbmap)
#define XFS_IOC_ZERO_RANGE _IOW ('X', 57, struct xfs_flock64)
-#define XFS_IOC_FREE_EOFBLOCKS _IOR ('X', 58, struct xfs_eofblocks)
+#define XFS_IOC_FREE_EOFBLOCKS _IOR ('X', 58, struct xfs_fs_eofblocks)
/*
* ioctl commands that replace IRIX syssgi()'s
diff --git a/include/xfs_quota_defs.h b/include/xfs_quota_defs.h
index e6b0d6e..b3b2b10 100644
--- a/include/xfs_quota_defs.h
+++ b/include/xfs_quota_defs.h
@@ -154,4 +154,8 @@ typedef __uint16_t xfs_qwarncnt_t;
(XFS_QMOPT_UQUOTA | XFS_QMOPT_PQUOTA | XFS_QMOPT_GQUOTA)
#define XFS_QMOPT_RESBLK_MASK (XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_RES_RTBLKS)
+extern int xfs_dqcheck(struct xfs_mount *mp, xfs_disk_dquot_t *ddq,
+ xfs_dqid_t id, uint type, uint flags, char *str);
+extern int xfs_calc_dquots_per_chunk(struct xfs_mount *mp, unsigned int nbblks);
+
#endif /* __XFS_QUOTA_H__ */
diff --git a/libxfs/xfs_attr_leaf.c b/libxfs/xfs_attr_leaf.c
index c09b0f3..fd52397 100644
--- a/libxfs/xfs_attr_leaf.c
+++ b/libxfs/xfs_attr_leaf.c
@@ -599,7 +599,7 @@ xfs_attr_shortform_getvalue(xfs_da_args_t *args)
xfs_attr_sf_entry_t *sfe;
int i;
- ASSERT(args->dp->i_d.di_aformat == XFS_IFINLINE);
+ ASSERT(args->dp->i_afp->if_flags == XFS_IFINLINE);
sf = (xfs_attr_shortform_t *)args->dp->i_afp->if_u1.if_data;
sfe = &sf->list[0];
for (i = 0; i < sf->hdr.count;
@@ -909,7 +909,6 @@ out:
return error;
}
-
/*========================================================================
* Routines used for growing the Btree.
*========================================================================*/
@@ -1270,7 +1269,6 @@ xfs_attr3_leaf_compact(
ichdr_dst->freemap[0].size = ichdr_dst->firstused -
ichdr_dst->freemap[0].base;
-
/* write the header back to initialise the underlying buffer */
xfs_attr3_leaf_hdr_to_disk(leaf_dst, ichdr_dst);
diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c
index 7336abf..3e80c64 100644
--- a/libxfs/xfs_bmap.c
+++ b/libxfs/xfs_bmap.c
@@ -510,8 +510,8 @@ xfs_bmap_trace_exlist(
/*
* Validate that the bmbt_irecs being returned from bmapi are valid
- * given the callers original parameters. Specifically check the
- * ranges of the returned irecs to ensure that they only extent beyond
+ * given the caller's original parameters. Specifically check the
+ * ranges of the returned irecs to ensure that they only extend beyond
* the given parameters if the XFS_BMAPI_ENTIRE flag was set.
*/
STATIC void
@@ -1515,7 +1515,7 @@ xfs_bmap_first_unused(
}
/*
- * Returns the file-relative block number of the last block + 1 before
+ * Returns the file-relative block number of the last block - 1 before
* last_block (input value) in the file.
* This is not based on i_size, it is based on the extent records.
* Returns 0 for local files, as they do not have extent records.
diff --git a/libxfs/xfs_bmap_btree.c b/libxfs/xfs_bmap_btree.c
index 2f6b48a..6211dc2 100644
--- a/libxfs/xfs_bmap_btree.c
+++ b/libxfs/xfs_bmap_btree.c
@@ -737,7 +737,7 @@ xfs_bmbt_verify(
* precise.
*/
level = be16_to_cpu(block->bb_level);
- if (level > MAX(mp->m_bm_maxlevels[0], mp->m_bm_maxlevels[1]))
+ if (level > max(mp->m_bm_maxlevels[0], mp->m_bm_maxlevels[1]))
return false;
if (be16_to_cpu(block->bb_numrecs) > mp->m_bmap_dmxr[level != 0])
return false;
diff --git a/libxfs/xfs_dir2_leaf.c b/libxfs/xfs_dir2_leaf.c
index c035c4d..683536e 100644
--- a/libxfs/xfs_dir2_leaf.c
+++ b/libxfs/xfs_dir2_leaf.c
@@ -1072,7 +1072,6 @@ xfs_dir3_leaf_compact_x1(
*highstalep = highstale;
}
-
/*
* Log the bests entries indicated from a leaf1 block.
*/
diff --git a/libxfs/xfs_dir2_node.c b/libxfs/xfs_dir2_node.c
index 6a245e5..10d1d81 100644
--- a/libxfs/xfs_dir2_node.c
+++ b/libxfs/xfs_dir2_node.c
@@ -1796,7 +1796,7 @@ xfs_dir2_node_addname_int(
/*
* Look at the current free entry. Is it good enough?
*
- * The bests initialisation should be where the buffer is read in
+ * The bests initialisation should be where the bufer is read in
* the above branch. But gcc is too stupid to realise that bests
* and the freehdr are actually initialised if they are placed
* there, so we have to do it here to avoid warnings. Blech.
diff --git a/libxfs/xfs_ialloc.c b/libxfs/xfs_ialloc.c
index 4683287..afe1a82 100644
--- a/libxfs/xfs_ialloc.c
+++ b/libxfs/xfs_ialloc.c
@@ -484,7 +484,7 @@ xfs_ialloc_next_ag(
/*
* Select an allocation group to look for a free inode in, based on the parent
- * inode and then mode. Return the allocation group buffer.
+ * inode and the mode. Return the allocation group buffer.
*/
STATIC xfs_agnumber_t
xfs_ialloc_ag_select(
@@ -706,7 +706,7 @@ xfs_dialloc_ag(
error = xfs_inobt_get_rec(cur, &rec, &j);
if (error)
goto error0;
- XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+ XFS_WANT_CORRUPTED_GOTO(j == 1, error0);
if (rec.ir_freecount > 0) {
/*
diff --git a/libxfs/xfs_inode_buf.c b/libxfs/xfs_inode_buf.c
index 67d5eb4..b796556 100644
--- a/libxfs/xfs_inode_buf.c
+++ b/libxfs/xfs_inode_buf.c
@@ -101,6 +101,7 @@ xfs_inode_buf_verify(
xfs_inobp_check(mp, bp);
}
+
static void
xfs_inode_buf_read_verify(
struct xfs_buf *bp)
@@ -299,6 +300,7 @@ xfs_dinode_verify(
return false;
return true;
}
+
void
xfs_dinode_calc_crc(
struct xfs_mount *mp,
diff --git a/libxfs/xfs_inode_fork.c b/libxfs/xfs_inode_fork.c
index 1c006f9..190690c 100644
--- a/libxfs/xfs_inode_fork.c
+++ b/libxfs/xfs_inode_fork.c
@@ -138,7 +138,8 @@ xfs_iformat_fork(
}
di_size = be64_to_cpu(dip->di_size);
- if (unlikely(di_size > XFS_DFORK_DSIZE(dip, ip->i_mount))) {
+ if (unlikely(di_size < 0 ||
+ di_size > XFS_DFORK_DSIZE(dip, ip->i_mount))) {
xfs_warn(ip->i_mount,
"corrupt inode %Lu (bad size %Ld for local inode).",
(unsigned long long) ip->i_ino,
@@ -444,7 +445,7 @@ xfs_iread_extents(
*
* The caller must not request to add more records than would fit in
* the on-disk inode root. If the if_broot is currently NULL, then
- * if we adding records one will be allocated. The caller must also
+ * if we are adding records, one will be allocated. The caller must also
* not request that the number of records go below zero, although
* it can go to zero.
*
diff --git a/libxfs/xfs_trans_resv.c b/libxfs/xfs_trans_resv.c
index 3e14b1c..1e59fad 100644
--- a/libxfs/xfs_trans_resv.c
+++ b/libxfs/xfs_trans_resv.c
@@ -49,7 +49,7 @@ xfs_calc_buf_res(
/*
* Logging inodes is really tricksy. They are logged in memory format,
- * which means that what we write into the log doesn't directory translate into
+ * which means that what we write into the log doesn't directly translate into
* the amount of space they use on disk.
*
* Case in point - btree format forks in memory format use more space than the
--
1.8.3.2
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 17/32] db: separate out straight buffer IO from map based IO.
[not found] <1380510944-8571-1-git-send-email-david@fromorbit.com>
` (15 preceding siblings ...)
2013-09-30 3:15 ` [PATCH 16/32] libxfs: Minor cleanup and bug fix sync Dave Chinner
@ 2013-09-30 3:15 ` Dave Chinner
2013-09-30 3:15 ` [PATCH 18/32] db: rewrite bbmap to use xfs_buf_map Dave Chinner
` (14 subsequent siblings)
31 siblings, 0 replies; 56+ messages in thread
From: Dave Chinner @ 2013-09-30 3:15 UTC (permalink / raw)
To: xfs
From: Dave Chinner <dchinner@redhat.com>
First step in converting to libxfs based IO.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
db/init.c | 7 ++--
db/io.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++++-------------
db/io.h | 5 +--
3 files changed, 104 insertions(+), 33 deletions(-)
diff --git a/db/init.c b/db/init.c
index 2932e51..0e88b56 100644
--- a/db/init.c
+++ b/db/init.c
@@ -55,7 +55,7 @@ init(
char **argv)
{
xfs_sb_t *sbp;
- void *bufp = NULL;
+ char bufp[BBSIZE];
int c;
setlocale(LC_ALL, "");
@@ -115,15 +115,14 @@ init(
exit(1);
}
- if (read_bbs(XFS_SB_DADDR, 1, &bufp, NULL)) {
+ if (read_buf(XFS_SB_DADDR, 1, bufp)) {
fprintf(stderr, _("%s: %s is invalid (cannot read first 512 "
"bytes)\n"), progname, fsdevice);
exit(1);
}
/* copy SB from buffer to in-core, converting architecture as we go */
- libxfs_sb_from_disk(&xmount.m_sb, bufp);
- xfree(bufp);
+ libxfs_sb_from_disk(&xmount.m_sb, (struct xfs_dsb *)bufp);
sbp = &xmount.m_sb;
if (sbp->sb_magicnum != XFS_SB_MAGIC) {
diff --git a/db/io.c b/db/io.c
index 39a1827..fa11646 100644
--- a/db/io.c
+++ b/db/io.c
@@ -417,8 +417,61 @@ ring_add(void)
}
}
-
int
+read_buf(
+ xfs_daddr_t bbno,
+ int count,
+ void *bufp)
+{
+ int err;
+
+ err = pread64(x.dfd, bufp, BBTOB(count), BBTOB(bbno));
+ if (err < 0)
+ err = errno;
+ else if (err < count)
+ err = -1;
+ return err;
+}
+
+static int
+write_buf(
+ xfs_daddr_t bbno,
+ int count,
+ void *bufp)
+{
+ int err;
+
+ err = pwrite64(x.dfd, bufp, BBTOB(count), BBTOB(bbno));
+ if (err < 0)
+ err = errno;
+ else if (err < count)
+ err = -1;
+ return err;
+}
+
+static void
+write_cur_buf(void)
+{
+ int ret;
+
+ ret = write_buf(iocur_top->bb, iocur_top->blen, iocur_top->buf);
+
+ if (ret == -1)
+ dbprintf(_("incomplete write, block: %lld\n"),
+ (iocur_base + iocur_sp)->bb);
+ else if (ret != 0)
+ dbprintf(_("write error: %s\n"), strerror(ret));
+
+ /* re-read buffer from disk */
+ ret = read_buf(iocur_top->bb, iocur_top->blen, iocur_top->buf);
+ if (ret == -1)
+ dbprintf(_("incomplete read, block: %lld\n"),
+ (iocur_base + iocur_sp)->bb);
+ else if (ret != 0)
+ dbprintf(_("read error: %s\n"), strerror(ret));
+}
+
+static int
write_bbs(
__int64_t bbno,
int count,
@@ -430,15 +483,14 @@ write_bbs(
int j;
int rval = EINVAL; /* initialize for zero `count' case */
- for (j = 0; j < count; j += bbmap ? 1 : count) {
- if (bbmap)
- bbno = bbmap->b[j];
+ for (j = 0; j < count; j++) {
+ bbno = bbmap->b[j];
if (lseek64(x.dfd, bbno << BBSHIFT, SEEK_SET) < 0) {
rval = errno;
dbprintf(_("can't seek in filesystem at bb %lld\n"), bbno);
return rval;
}
- c = BBTOB(bbmap ? 1 : count);
+ c = BBTOB(1);
i = (int)write(x.dfd, (char *)bufp + BBTOB(j), c);
if (i < 0) {
rval = errno;
@@ -452,7 +504,7 @@ write_bbs(
return rval;
}
-int
+static int
read_bbs(
__int64_t bbno,
int count,
@@ -473,9 +525,8 @@ read_bbs(
buf = xmalloc(c);
else
buf = *bufp;
- for (j = 0; j < count; j += bbmap ? 1 : count) {
- if (bbmap)
- bbno = bbmap->b[j];
+ for (j = 0; j < count; j++) {
+ bbno = bbmap->b[j];
if (lseek64(x.dfd, bbno << BBSHIFT, SEEK_SET) < 0) {
rval = errno;
dbprintf(_("can't seek in filesystem at bb %lld\n"), bbno);
@@ -483,7 +534,7 @@ read_bbs(
xfree(buf);
buf = NULL;
} else {
- c = BBTOB(bbmap ? 1 : count);
+ c = BBTOB(1);
i = (int)read(x.dfd, (char *)buf + BBTOB(j), c);
if (i < 0) {
rval = errno;
@@ -506,22 +557,19 @@ read_bbs(
return rval;
}
-void
-write_cur(void)
+static void
+write_cur_bbs(void)
{
int ret;
- if (iocur_sp < 0) {
- dbprintf(_("nothing to write\n"));
- return;
- }
ret = write_bbs(iocur_top->bb, iocur_top->blen, iocur_top->buf,
- iocur_top->use_bbmap ? &iocur_top->bbmap : NULL);
+ &iocur_top->bbmap);
if (ret == -1)
dbprintf(_("incomplete write, block: %lld\n"),
(iocur_base + iocur_sp)->bb);
else if (ret != 0)
dbprintf(_("write error: %s\n"), strerror(ret));
+
/* re-read buffer from disk */
ret = read_bbs(iocur_top->bb, iocur_top->blen, &iocur_top->buf,
iocur_top->use_bbmap ? &iocur_top->bbmap : NULL);
@@ -533,6 +581,20 @@ write_cur(void)
}
void
+write_cur(void)
+{
+ if (iocur_sp < 0) {
+ dbprintf(_("nothing to write\n"));
+ return;
+ }
+
+ if (iocur_top->use_bbmap)
+ write_cur_bbs();
+ else
+ write_cur_buf();
+}
+
+void
set_cur(
const typ_t *t,
__int64_t d,
@@ -549,17 +611,32 @@ set_cur(
return;
}
-#ifdef DEBUG
- if (bbmap)
- printf(_("xfs_db got a bbmap for %lld\n"), (long long)d);
-#endif
ino = iocur_top->ino;
dirino = iocur_top->dirino;
mode = iocur_top->mode;
pop_cur();
push_cur();
- if (read_bbs(d, c, &iocur_top->buf, bbmap))
- return;
+
+ if (bbmap) {
+#ifdef DEBUG
+ printf(_("xfs_db got a bbmap for %lld\n"), (long long)d);
+#endif
+
+ if (read_bbs(d, c, &iocur_top->buf, bbmap))
+ return;
+ iocur_top->bbmap = *bbmap;
+ iocur_top->use_bbmap = 1;
+ } else {
+ if (!iocur_top->buf) {
+ iocur_top->buf = malloc(BBTOB(c));
+ if (!iocur_top->buf)
+ return;
+ }
+ if (read_buf(d, c, iocur_top->buf))
+ return;
+ iocur_top->use_bbmap = 0;
+ }
+
iocur_top->bb = d;
iocur_top->blen = c;
iocur_top->boff = 0;
@@ -570,8 +647,6 @@ set_cur(
iocur_top->ino = ino;
iocur_top->dirino = dirino;
iocur_top->mode = mode;
- if ((iocur_top->use_bbmap = (bbmap != NULL)))
- iocur_top->bbmap = *bbmap;
/* store location in ring */
if (ring_flag)
diff --git a/db/io.h b/db/io.h
index 549aad9..9ea6223 100644
--- a/db/io.h
+++ b/db/io.h
@@ -52,10 +52,7 @@ extern void off_cur(int off, int len);
extern void pop_cur(void);
extern void print_iocur(char *tag, iocur_t *ioc);
extern void push_cur(void);
-extern int read_bbs(__int64_t daddr, int count, void **bufp,
- bbmap_t *bbmap);
-extern int write_bbs(__int64_t daddr, int count, void *bufp,
- bbmap_t *bbmap);
+extern int read_buf(__int64_t daddr, int count, void *bufp);
extern void write_cur(void);
extern void set_cur(const struct typ *t, __int64_t d, int c, int ring_add,
bbmap_t *bbmap);
--
1.8.3.2
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 18/32] db: rewrite bbmap to use xfs_buf_map
[not found] <1380510944-8571-1-git-send-email-david@fromorbit.com>
` (16 preceding siblings ...)
2013-09-30 3:15 ` [PATCH 17/32] db: separate out straight buffer IO from map based IO Dave Chinner
@ 2013-09-30 3:15 ` Dave Chinner
2013-09-30 3:15 ` [PATCH 19/32] db: rewrite IO engine to use libxfs Dave Chinner
` (13 subsequent siblings)
31 siblings, 0 replies; 56+ messages in thread
From: Dave Chinner @ 2013-09-30 3:15 UTC (permalink / raw)
To: xfs
From: Dave Chinner <dchinner@redhat.com>
Use the libxfs struct xfs_buf_map for recording the extent layout of
discontiguous buffers and convert the read/write to decode them
directory and use read_buf/write_buf to do the extent IO. This
brings the physical xfs_db IO code to be very close to the model
that libxfs uses.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
db/bmap.c | 15 ++++-----------
db/io.c | 58 ++++++++++++----------------------------------------------
db/io.h | 3 ++-
3 files changed, 18 insertions(+), 58 deletions(-)
diff --git a/db/bmap.c b/db/bmap.c
index 0ef7a62..3951b9f 100644
--- a/db/bmap.c
+++ b/db/bmap.c
@@ -293,20 +293,13 @@ make_bbmap(
int nex,
bmap_ext_t *bmp)
{
- int d;
- xfs_dfsbno_t dfsbno;
int i;
- int j;
- int k;
- for (i = 0, d = 0; i < nex; i++) {
- dfsbno = bmp[i].startblock;
- for (j = 0; j < bmp[i].blockcount; j++, dfsbno++) {
- for (k = 0; k < blkbb; k++)
- bbmap->b[d++] =
- XFS_FSB_TO_DADDR(mp, dfsbno) + k;
- }
+ for (i = 0; i < nex; i++) {
+ bbmap->b[i].bm_bn = XFS_FSB_TO_DADDR(mp, bmp[i].startblock);
+ bbmap->b[i].bm_len = XFS_FSB_TO_BB(mp, bmp[i].blockcount);
}
+ bbmap->nmaps = nex;
}
static xfs_fsblock_t
diff --git a/db/io.c b/db/io.c
index fa11646..01a5970 100644
--- a/db/io.c
+++ b/db/io.c
@@ -478,28 +478,16 @@ write_bbs(
void *bufp,
bbmap_t *bbmap)
{
- int c;
- int i;
int j;
int rval = EINVAL; /* initialize for zero `count' case */
- for (j = 0; j < count; j++) {
- bbno = bbmap->b[j];
- if (lseek64(x.dfd, bbno << BBSHIFT, SEEK_SET) < 0) {
- rval = errno;
- dbprintf(_("can't seek in filesystem at bb %lld\n"), bbno);
- return rval;
- }
- c = BBTOB(1);
- i = (int)write(x.dfd, (char *)bufp + BBTOB(j), c);
- if (i < 0) {
- rval = errno;
- } else if (i < c) {
- rval = -1;
- } else
- rval = 0;
+ for (j = 0; j < count;) {
+ rval = write_buf(bbmap->b[j].bm_bn, bbmap->b[j].bm_len,
+ (char *)bufp + BBTOB(j));
if (rval)
break;
+
+ j += bbmap->b[j].bm_len;
}
return rval;
}
@@ -512,45 +500,23 @@ read_bbs(
bbmap_t *bbmap)
{
void *buf;
- int c;
- int i;
int j;
int rval = EINVAL;
if (count <= 0)
count = 1;
- c = BBTOB(count);
if (*bufp == NULL)
- buf = xmalloc(c);
+ buf = xmalloc(BBTOB(count));
else
buf = *bufp;
- for (j = 0; j < count; j++) {
- bbno = bbmap->b[j];
- if (lseek64(x.dfd, bbno << BBSHIFT, SEEK_SET) < 0) {
- rval = errno;
- dbprintf(_("can't seek in filesystem at bb %lld\n"), bbno);
- if (*bufp == NULL)
- xfree(buf);
- buf = NULL;
- } else {
- c = BBTOB(1);
- i = (int)read(x.dfd, (char *)buf + BBTOB(j), c);
- if (i < 0) {
- rval = errno;
- if (*bufp == NULL)
- xfree(buf);
- buf = NULL;
- } else if (i < c) {
- rval = -1;
- if (*bufp == NULL)
- xfree(buf);
- buf = NULL;
- } else
- rval = 0;
- }
- if (buf == NULL)
+ for (j = 0; j < count;) {
+ rval = read_buf(bbmap->b[j].bm_bn, bbmap->b[j].bm_len,
+ (char *)buf + BBTOB(j));
+ if (rval)
break;
+
+ j += bbmap->b[j].bm_len;
}
if (*bufp == NULL)
*bufp = buf;
diff --git a/db/io.h b/db/io.h
index 9ea6223..c7641d5 100644
--- a/db/io.h
+++ b/db/io.h
@@ -20,7 +20,8 @@ struct typ;
#define BBMAP_SIZE (XFS_MAX_BLOCKSIZE / BBSIZE)
typedef struct bbmap {
- __int64_t b[BBMAP_SIZE];
+ int nmaps;
+ struct xfs_buf_map b[BBMAP_SIZE];
} bbmap_t;
typedef struct iocur {
--
1.8.3.2
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 19/32] db: rewrite IO engine to use libxfs
[not found] <1380510944-8571-1-git-send-email-david@fromorbit.com>
` (17 preceding siblings ...)
2013-09-30 3:15 ` [PATCH 18/32] db: rewrite bbmap to use xfs_buf_map Dave Chinner
@ 2013-09-30 3:15 ` Dave Chinner
2013-09-30 3:15 ` [PATCH 20/32] db: introduce verifier support into set_cur Dave Chinner
` (12 subsequent siblings)
31 siblings, 0 replies; 56+ messages in thread
From: Dave Chinner @ 2013-09-30 3:15 UTC (permalink / raw)
To: xfs
From: Dave Chinner <dchinner@redhat.com>
Now that we have buffers and xfs_buf_maps, it is relatively easy to
convert the IO engine to use libxfs routines. This gets rid of the
most of the differences between mapped and straight buffer reads,
and tracks xfs_bufs directly in the IO context that is being used.
This is not yet a perfect solution, as xfs_db does different sized
IOs for the same block range which will throw warnings like:
xfs_db> inode 64
7ffff7fde740: Badness in key lookup (length)
bp=(bno 0x40, len 8192 bytes) key=(bno 0x40, len 4096 bytes)
xfs_db>
This is when first displaying an inode in the root inode chunk.
These will need to be dealt with on a case by case basis.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
db/init.c | 25 ++++++--
db/io.c | 176 ++++++++++++++-----------------------------------------
db/io.h | 4 +-
include/libxfs.h | 3 +
libxfs/init.c | 5 ++
libxfs/rdwr.c | 61 ++++++++++++-------
6 files changed, 116 insertions(+), 158 deletions(-)
diff --git a/db/init.c b/db/init.c
index 0e88b56..b1cddca 100644
--- a/db/init.c
+++ b/db/init.c
@@ -54,8 +54,8 @@ init(
int argc,
char **argv)
{
- xfs_sb_t *sbp;
- char bufp[BBSIZE];
+ struct xfs_sb *sbp;
+ struct xfs_buf *bp;
int c;
setlocale(LC_ALL, "");
@@ -115,14 +115,25 @@ init(
exit(1);
}
- if (read_buf(XFS_SB_DADDR, 1, bufp)) {
+ /*
+ * Read the superblock, but don't validate it - we are a diagnostic
+ * tool and so need to be able to mount busted filesystems.
+ */
+ memset(&xmount, 0, sizeof(struct xfs_mount));
+ libxfs_buftarg_init(&xmount, x.ddev, x.logdev, x.rtdev);
+ bp = libxfs_readbuf(xmount.m_ddev_targp, XFS_SB_DADDR,
+ 1 << (XFS_MAX_SECTORSIZE_LOG - BBSHIFT), 0, NULL);
+
+ if (!bp || bp->b_error) {
fprintf(stderr, _("%s: %s is invalid (cannot read first 512 "
"bytes)\n"), progname, fsdevice);
exit(1);
}
/* copy SB from buffer to in-core, converting architecture as we go */
- libxfs_sb_from_disk(&xmount.m_sb, (struct xfs_dsb *)bufp);
+ libxfs_sb_from_disk(&xmount.m_sb, XFS_BUF_TO_SBP(bp));
+ libxfs_putbuf(bp);
+ libxfs_purgebuf(bp);
sbp = &xmount.m_sb;
if (sbp->sb_magicnum != XFS_SB_MAGIC) {
@@ -201,6 +212,12 @@ main(
}
close_devices:
+ /*
+ * make sure that we pop the last buffer context we held so that the
+ * buffer is released before purge the caches during unmount.
+ */
+ pop_cur();
+ libxfs_umount(mp);
if (x.ddev)
libxfs_device_close(x.ddev);
if (x.logdev && x.logdev != x.ddev)
diff --git a/db/io.c b/db/io.c
index 01a5970..9129963 100644
--- a/db/io.c
+++ b/db/io.c
@@ -104,8 +104,12 @@ pop_cur(void)
dbprintf(_("can't pop anything from I/O stack\n"));
return;
}
- if (iocur_top->buf)
- xfree(iocur_top->buf);
+ if (iocur_top->bp)
+ libxfs_putbuf(iocur_top->bp);
+ if (iocur_top->bbmap) {
+ free(iocur_top->bbmap);
+ iocur_top->bbmap = NULL;
+ }
if (--iocur_sp >= 0) {
iocur_top = iocur_base + iocur_sp;
cur_typ = iocur_top->typ;
@@ -147,10 +151,11 @@ print_iocur(
dbprintf(_("\tbuffer block %lld (fsbno %lld), %d bb%s\n"), ioc->bb,
(xfs_dfsbno_t)XFS_DADDR_TO_FSB(mp, ioc->bb), ioc->blen,
ioc->blen == 1 ? "" : "s");
- if (ioc->use_bbmap) {
+ if (ioc->bbmap) {
dbprintf(_("\tblock map"));
- for (i = 0; i < ioc->blen; i++)
- dbprintf(" %d:%lld", i, ioc->bbmap.b[i]);
+ for (i = 0; i < ioc->bbmap->nmaps; i++)
+ dbprintf(" %lld:%d", ioc->bbmap->b[i].bm_bn,
+ ioc->bbmap->b[i].bm_len);
dbprintf("\n");
}
dbprintf(_("\tinode %lld, dir inode %lld, type %s\n"), ioc->ino,
@@ -238,7 +243,7 @@ push_f(
else
set_cur(iocur_top[-1].typ, iocur_top[-1].bb,
iocur_top[-1].blen, DB_RING_IGN,
- iocur_top[-1].use_bbmap ? &iocur_top[-1].bbmap : NULL);
+ iocur_top[-1].bbmap);
/* run requested command */
if (argc>1)
@@ -280,8 +285,7 @@ forward_f(
iocur_ring[ring_current].bb,
iocur_ring[ring_current].blen,
DB_RING_IGN,
- iocur_ring[ring_current].use_bbmap ?
- &iocur_ring[ring_current].bbmap : NULL);
+ iocur_ring[ring_current].bbmap);
return 0;
}
@@ -321,8 +325,7 @@ back_f(
iocur_ring[ring_current].bb,
iocur_ring[ring_current].blen,
DB_RING_IGN,
- iocur_ring[ring_current].use_bbmap ?
- &iocur_ring[ring_current].bbmap : NULL);
+ iocur_ring[ring_current].bbmap);
return 0;
}
@@ -362,7 +365,7 @@ ring_f(
iocur_ring[index].bb,
iocur_ring[index].blen,
DB_RING_IGN,
- iocur_ring[index].use_bbmap ? &iocur_ring[index].bbmap : NULL);
+ iocur_ring[index].bbmap);
return 0;
}
@@ -417,132 +420,37 @@ ring_add(void)
}
}
-int
-read_buf(
- xfs_daddr_t bbno,
- int count,
- void *bufp)
-{
- int err;
-
- err = pread64(x.dfd, bufp, BBTOB(count), BBTOB(bbno));
- if (err < 0)
- err = errno;
- else if (err < count)
- err = -1;
- return err;
-}
-
-static int
-write_buf(
- xfs_daddr_t bbno,
- int count,
- void *bufp)
-{
- int err;
-
- err = pwrite64(x.dfd, bufp, BBTOB(count), BBTOB(bbno));
- if (err < 0)
- err = errno;
- else if (err < count)
- err = -1;
- return err;
-}
-
static void
write_cur_buf(void)
{
int ret;
- ret = write_buf(iocur_top->bb, iocur_top->blen, iocur_top->buf);
-
- if (ret == -1)
- dbprintf(_("incomplete write, block: %lld\n"),
- (iocur_base + iocur_sp)->bb);
- else if (ret != 0)
+ ret = libxfs_writebufr(iocur_top->bp);
+ if (ret != 0)
dbprintf(_("write error: %s\n"), strerror(ret));
/* re-read buffer from disk */
- ret = read_buf(iocur_top->bb, iocur_top->blen, iocur_top->buf);
- if (ret == -1)
- dbprintf(_("incomplete read, block: %lld\n"),
- (iocur_base + iocur_sp)->bb);
- else if (ret != 0)
+ ret = libxfs_readbufr(mp->m_ddev_targp, iocur_top->bb, iocur_top->bp,
+ iocur_top->blen, 0);
+ if (ret != 0)
dbprintf(_("read error: %s\n"), strerror(ret));
}
-static int
-write_bbs(
- __int64_t bbno,
- int count,
- void *bufp,
- bbmap_t *bbmap)
-{
- int j;
- int rval = EINVAL; /* initialize for zero `count' case */
-
- for (j = 0; j < count;) {
- rval = write_buf(bbmap->b[j].bm_bn, bbmap->b[j].bm_len,
- (char *)bufp + BBTOB(j));
- if (rval)
- break;
-
- j += bbmap->b[j].bm_len;
- }
- return rval;
-}
-
-static int
-read_bbs(
- __int64_t bbno,
- int count,
- void **bufp,
- bbmap_t *bbmap)
-{
- void *buf;
- int j;
- int rval = EINVAL;
-
- if (count <= 0)
- count = 1;
-
- if (*bufp == NULL)
- buf = xmalloc(BBTOB(count));
- else
- buf = *bufp;
- for (j = 0; j < count;) {
- rval = read_buf(bbmap->b[j].bm_bn, bbmap->b[j].bm_len,
- (char *)buf + BBTOB(j));
- if (rval)
- break;
-
- j += bbmap->b[j].bm_len;
- }
- if (*bufp == NULL)
- *bufp = buf;
- return rval;
-}
-
static void
write_cur_bbs(void)
{
int ret;
- ret = write_bbs(iocur_top->bb, iocur_top->blen, iocur_top->buf,
- &iocur_top->bbmap);
- if (ret == -1)
- dbprintf(_("incomplete write, block: %lld\n"),
- (iocur_base + iocur_sp)->bb);
- else if (ret != 0)
+ ret = libxfs_writebufr(iocur_top->bp);
+ if (ret != 0)
dbprintf(_("write error: %s\n"), strerror(ret));
+
/* re-read buffer from disk */
- ret = read_bbs(iocur_top->bb, iocur_top->blen, &iocur_top->buf,
- iocur_top->use_bbmap ? &iocur_top->bbmap : NULL);
- if (ret == -1)
- dbprintf(_("incomplete read, block: %lld\n"),
- (iocur_base + iocur_sp)->bb);
- else if (ret != 0)
+ ret = libxfs_readbufr_map(mp->m_ddev_targp, iocur_top->bp,
+ iocur_top->bbmap->b, iocur_top->bbmap->nmaps,
+ 0);
+ if (ret != 0)
dbprintf(_("read error: %s\n"), strerror(ret));
}
@@ -554,7 +462,7 @@ write_cur(void)
return;
}
- if (iocur_top->use_bbmap)
+ if (iocur_top->bbmap)
write_cur_bbs();
else
write_cur_buf();
@@ -568,6 +476,7 @@ set_cur(
int ring_flag,
bbmap_t *bbmap)
{
+ struct xfs_buf *bp;
xfs_ino_t dirino;
xfs_ino_t ino;
__uint16_t mode;
@@ -585,23 +494,28 @@ set_cur(
if (bbmap) {
#ifdef DEBUG
+ int i;
printf(_("xfs_db got a bbmap for %lld\n"), (long long)d);
+ printf(_("\tblock map"));
+ for (i = 0; i < bbmap->nmaps; i++)
+ printf(" %lld:%d", (long long)bbmap->b[i].bm_bn,
+ bbmap->b[i].bm_len);
+ printf("\n");
#endif
-
- if (read_bbs(d, c, &iocur_top->buf, bbmap))
+ iocur_top->bbmap = malloc(sizeof(struct bbmap));
+ if (!iocur_top->bbmap)
return;
- iocur_top->bbmap = *bbmap;
- iocur_top->use_bbmap = 1;
+ memcpy(iocur_top->bbmap, bbmap, sizeof(struct bbmap));
+ bp = libxfs_readbuf_map(mp->m_ddev_targp, bbmap->b,
+ bbmap->nmaps, 0, NULL);
} else {
- if (!iocur_top->buf) {
- iocur_top->buf = malloc(BBTOB(c));
- if (!iocur_top->buf)
- return;
- }
- if (read_buf(d, c, iocur_top->buf))
- return;
- iocur_top->use_bbmap = 0;
+ bp = libxfs_readbuf(mp->m_ddev_targp, d, c, 0, NULL);
+ iocur_top->bbmap = NULL;
}
+ if (!bp || bp->b_error)
+ return;
+ iocur_top->buf = bp->b_addr;
+ iocur_top->bp = bp;
iocur_top->bb = d;
iocur_top->blen = c;
diff --git a/db/io.h b/db/io.h
index c7641d5..2c47ccc 100644
--- a/db/io.h
+++ b/db/io.h
@@ -36,8 +36,8 @@ typedef struct iocur {
__uint16_t mode; /* current inode's mode */
xfs_off_t off; /* fs offset of "data" in bytes */
const struct typ *typ; /* type of "data" */
- int use_bbmap; /* set if bbmap is valid */
- bbmap_t bbmap; /* map daddr if fragmented */
+ bbmap_t *bbmap; /* map daddr if fragmented */
+ struct xfs_buf *bp; /* underlying buffer */
} iocur_t;
#define DB_RING_ADD 1 /* add to ring on set_cur */
diff --git a/include/libxfs.h b/include/libxfs.h
index f10ab59..08fd0b3 100644
--- a/include/libxfs.h
+++ b/include/libxfs.h
@@ -447,7 +447,10 @@ extern xfs_buf_t *libxfs_getbufr(struct xfs_buftarg *, xfs_daddr_t, int);
extern void libxfs_putbufr(xfs_buf_t *);
extern int libxfs_writebuf_int(xfs_buf_t *, int);
+extern int libxfs_writebufr(struct xfs_buf *);
extern int libxfs_readbufr(struct xfs_buftarg *, xfs_daddr_t, xfs_buf_t *, int, int);
+extern int libxfs_readbufr_map(struct xfs_buftarg *, struct xfs_buf *,
+ struct xfs_buf_map *, int, int);
extern int libxfs_bhash_size;
extern int libxfs_ihash_size;
diff --git a/libxfs/init.c b/libxfs/init.c
index db7eeea..229aa50 100644
--- a/libxfs/init.c
+++ b/libxfs/init.c
@@ -688,6 +688,9 @@ libxfs_mount(
libxfs_buftarg_init(mp, dev, logdev, rtdev);
mp->m_flags = (LIBXFS_MOUNT_32BITINODES|LIBXFS_MOUNT_32BITINOOPT);
+ if (flags & LIBXFS_MOUNT_ROOTINOS)
+ mp->m_flags |= LIBXFS_MOUNT_ROOTINOS;
+
mp->m_sb = *sb;
INIT_RADIX_TREE(&mp->m_perag_tree, GFP_KERNEL);
sbp = &(mp->m_sb);
@@ -866,6 +869,8 @@ libxfs_umount(xfs_mount_t *mp)
int agno;
libxfs_rtmount_destroy(mp);
+ if ((mp->m_flags & LIBXFS_MOUNT_ROOTINOS) && mp->m_rootip)
+ libxfs_iput(mp->m_rootip, 0);
libxfs_icache_purge();
libxfs_bcache_purge();
diff --git a/libxfs/rdwr.c b/libxfs/rdwr.c
index 13dbd23..8d8bcfc 100644
--- a/libxfs/rdwr.c
+++ b/libxfs/rdwr.c
@@ -719,30 +719,18 @@ libxfs_readbuf(struct xfs_buftarg *btp, xfs_daddr_t blkno, int len, int flags,
return bp;
}
-struct xfs_buf *
-libxfs_readbuf_map(struct xfs_buftarg *btp, struct xfs_buf_map *map, int nmaps,
- int flags, const struct xfs_buf_ops *ops)
+int
+libxfs_readbufr_map(struct xfs_buftarg *btp, struct xfs_buf *bp,
+ struct xfs_buf_map *map, int nmaps, int flags)
{
- xfs_buf_t *bp;
- int error = 0;
- int fd;
- int i;
- char *buf;
-
- if (nmaps == 1)
- return libxfs_readbuf(btp, map[0].bm_bn, map[0].bm_len,
- flags, ops);
-
- bp = libxfs_getbuf_map(btp, map, nmaps);
- if (!bp)
- return NULL;
+ int fd = libxfs_device_to_fd(btp->dev);
+ int error = 0;
+ char *buf;
+ int i;
- bp->b_error = 0;
- bp->b_ops = ops;
- if ((bp->b_flags & (LIBXFS_B_UPTODATE|LIBXFS_B_DIRTY)))
- return bp;
+ ASSERT(BBTOB(len) <= bp->b_bcount);
- ASSERT(bp->b_nmaps = nmaps);
+ ASSERT(bp->b_nmaps == nmaps);
fd = libxfs_device_to_fd(btp->dev);
buf = bp->b_addr;
@@ -762,6 +750,37 @@ libxfs_readbuf_map(struct xfs_buftarg *btp, struct xfs_buf_map *map, int nmaps,
offset += len;
}
+ if (!error);
+ bp->b_flags |= LIBXFS_B_UPTODATE;
+#ifdef IO_DEBUG
+ printf("%lx: %s: read %u bytes, error %d, blkno=0x%llx(0x%llx), %p\n",
+ pthread_self(), __FUNCTION__, , error,
+ (long long)LIBXFS_BBTOOFF64(blkno), (long long)blkno, bp);
+#endif
+ return error;
+}
+
+struct xfs_buf *
+libxfs_readbuf_map(struct xfs_buftarg *btp, struct xfs_buf_map *map, int nmaps,
+ int flags, const struct xfs_buf_ops *ops)
+{
+ struct xfs_buf *bp;
+ int error = 0;
+
+ if (nmaps == 1)
+ return libxfs_readbuf(btp, map[0].bm_bn, map[0].bm_len,
+ flags, ops);
+
+ bp = libxfs_getbuf_map(btp, map, nmaps);
+ if (!bp)
+ return NULL;
+
+ bp->b_error = 0;
+ bp->b_ops = ops;
+ if ((bp->b_flags & (LIBXFS_B_UPTODATE|LIBXFS_B_DIRTY)))
+ return bp;
+
+ error = libxfs_readbufr_map(btp, bp, map, nmaps, flags);
if (!error) {
bp->b_flags |= LIBXFS_B_UPTODATE;
if (bp->b_ops)
--
1.8.3.2
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 20/32] db: introduce verifier support into set_cur
[not found] <1380510944-8571-1-git-send-email-david@fromorbit.com>
` (18 preceding siblings ...)
2013-09-30 3:15 ` [PATCH 19/32] db: rewrite IO engine to use libxfs Dave Chinner
@ 2013-09-30 3:15 ` Dave Chinner
2013-09-30 3:15 ` [PATCH 21/32] db: indicate if the CRC on a buffer is correct or not Dave Chinner
` (11 subsequent siblings)
31 siblings, 0 replies; 56+ messages in thread
From: Dave Chinner @ 2013-09-30 3:15 UTC (permalink / raw)
To: xfs
From: Dave Chinner <dchinner@redhat.com>
To be able to use read and write verifiers, we need to pass the
verifier to the IO routines. We do this via the set_cur() function
used to trigger reading the buffer.
For most metadata types, there is only one type of verifier needed.
For these, we can simply add the verifier to the type table entry
for the given type and use that directly. This type entry is already
carried around by the IO context, so if we ever need to get it again
we have direct access to it in the context we'll be doing IO.
Only attach the verifiers to the v5 filesystem type table; there is
not need for them on v4 filesystems as we don't have to verify or
calculate CRCs for them.
There are some metadata types that have more than one buffer format,
or aren't based in directly in buffers. For these, leave the type
table verifier NULL for now - these will need to be addressed
individually.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
db/io.c | 13 +++++++---
db/type.c | 88 ++++++++++++++++++++++++++++++++++-----------------------------
db/type.h | 1 +
3 files changed, 59 insertions(+), 43 deletions(-)
diff --git a/db/io.c b/db/io.c
index 9129963..c9452f2 100644
--- a/db/io.c
+++ b/db/io.c
@@ -480,12 +480,14 @@ set_cur(
xfs_ino_t dirino;
xfs_ino_t ino;
__uint16_t mode;
+ const struct xfs_buf_ops *ops = t ? t->bops : NULL;
if (iocur_sp < 0) {
dbprintf(_("set_cur no stack element to set\n"));
return;
}
+
ino = iocur_top->ino;
dirino = iocur_top->dirino;
mode = iocur_top->mode;
@@ -507,12 +509,17 @@ set_cur(
return;
memcpy(iocur_top->bbmap, bbmap, sizeof(struct bbmap));
bp = libxfs_readbuf_map(mp->m_ddev_targp, bbmap->b,
- bbmap->nmaps, 0, NULL);
+ bbmap->nmaps, 0, ops);
} else {
- bp = libxfs_readbuf(mp->m_ddev_targp, d, c, 0, NULL);
+ bp = libxfs_readbuf(mp->m_ddev_targp, d, c, 0, ops);
iocur_top->bbmap = NULL;
}
- if (!bp || bp->b_error)
+
+ /*
+ * keep the buffer even if the verifier says it is corrupted.
+ * We're a diagnostic tool, after all.
+ */
+ if (!bp || (bp->b_error && bp->b_error != EFSCORRUPTED))
return;
iocur_top->buf = bp->b_addr;
iocur_top->bp = bp;
diff --git a/db/type.c b/db/type.c
index 64e2ef4..b3f3d87 100644
--- a/db/type.c
+++ b/db/type.c
@@ -50,50 +50,58 @@ static const cmdinfo_t type_cmd =
N_("set/show current data type"), NULL };
static const typ_t __typtab[] = {
- { TYP_AGF, "agf", handle_struct, agf_hfld },
- { TYP_AGFL, "agfl", handle_struct, agfl_hfld },
- { TYP_AGI, "agi", handle_struct, agi_hfld },
- { TYP_ATTR, "attr", handle_struct, attr_hfld },
- { TYP_BMAPBTA, "bmapbta", handle_struct, bmapbta_hfld },
- { TYP_BMAPBTD, "bmapbtd", handle_struct, bmapbtd_hfld },
- { TYP_BNOBT, "bnobt", handle_struct, bnobt_hfld },
- { TYP_CNTBT, "cntbt", handle_struct, cntbt_hfld },
- { TYP_DATA, "data", handle_block, NULL },
- { TYP_DIR2, "dir2", handle_struct, dir2_hfld },
- { TYP_DQBLK, "dqblk", handle_struct, dqblk_hfld },
- { TYP_INOBT, "inobt", handle_struct, inobt_hfld },
- { TYP_INODATA, "inodata", NULL, NULL },
- { TYP_INODE, "inode", handle_struct, inode_hfld },
- { TYP_LOG, "log", NULL, NULL },
- { TYP_RTBITMAP, "rtbitmap", NULL, NULL },
- { TYP_RTSUMMARY, "rtsummary", NULL, NULL },
- { TYP_SB, "sb", handle_struct, sb_hfld },
- { TYP_SYMLINK, "symlink", handle_string, NULL },
- { TYP_TEXT, "text", handle_text, NULL },
+ { TYP_AGF, "agf", handle_struct, agf_hfld, NULL },
+ { TYP_AGFL, "agfl", handle_struct, agfl_hfld, NULL },
+ { TYP_AGI, "agi", handle_struct, agi_hfld, NULL },
+ { TYP_ATTR, "attr", handle_struct, attr_hfld, NULL },
+ { TYP_BMAPBTA, "bmapbta", handle_struct, bmapbta_hfld, NULL },
+ { TYP_BMAPBTD, "bmapbtd", handle_struct, bmapbtd_hfld, NULL },
+ { TYP_BNOBT, "bnobt", handle_struct, bnobt_hfld, NULL },
+ { TYP_CNTBT, "cntbt", handle_struct, cntbt_hfld, NULL },
+ { TYP_DATA, "data", handle_block, NULL, NULL },
+ { TYP_DIR2, "dir2", handle_struct, dir2_hfld, NULL },
+ { TYP_DQBLK, "dqblk", handle_struct, dqblk_hfld, NULL },
+ { TYP_INOBT, "inobt", handle_struct, inobt_hfld, NULL },
+ { TYP_INODATA, "inodata", NULL, NULL, NULL },
+ { TYP_INODE, "inode", handle_struct, inode_hfld, NULL },
+ { TYP_LOG, "log", NULL, NULL, NULL },
+ { TYP_RTBITMAP, "rtbitmap", NULL, NULL, NULL },
+ { TYP_RTSUMMARY, "rtsummary", NULL, NULL, NULL },
+ { TYP_SB, "sb", handle_struct, sb_hfld, NULL },
+ { TYP_SYMLINK, "symlink", handle_string, NULL, NULL },
+ { TYP_TEXT, "text", handle_text, NULL, NULL },
{ TYP_NONE, NULL }
};
static const typ_t __typtab_crc[] = {
- { TYP_AGF, "agf", handle_struct, agf_hfld },
- { TYP_AGFL, "agfl", handle_struct, agfl_crc_hfld },
- { TYP_AGI, "agi", handle_struct, agi_hfld },
- { TYP_ATTR, "attr3", handle_struct, attr3_hfld },
- { TYP_BMAPBTA, "bmapbta", handle_struct, bmapbta_crc_hfld },
- { TYP_BMAPBTD, "bmapbtd", handle_struct, bmapbtd_crc_hfld },
- { TYP_BNOBT, "bnobt", handle_struct, bnobt_crc_hfld },
- { TYP_CNTBT, "cntbt", handle_struct, cntbt_crc_hfld },
- { TYP_DATA, "data", handle_block, NULL },
- { TYP_DIR2, "dir3", handle_struct, dir3_hfld },
- { TYP_DQBLK, "dqblk", handle_struct, dqblk_hfld },
- { TYP_INOBT, "inobt", handle_struct, inobt_crc_hfld },
- { TYP_INODATA, "inodata", NULL, NULL },
- { TYP_INODE, "inode", handle_struct, inode_crc_hfld },
- { TYP_LOG, "log", NULL, NULL },
- { TYP_RTBITMAP, "rtbitmap", NULL, NULL },
- { TYP_RTSUMMARY, "rtsummary", NULL, NULL },
- { TYP_SB, "sb", handle_struct, sb_hfld },
- { TYP_SYMLINK, "symlink", handle_struct, symlink_crc_hfld },
- { TYP_TEXT, "text", handle_text, NULL },
+ { TYP_AGF, "agf", handle_struct, agf_hfld, &xfs_agf_buf_ops },
+ { TYP_AGFL, "agfl", handle_struct, agfl_crc_hfld, &xfs_agfl_buf_ops },
+ { TYP_AGI, "agi", handle_struct, agi_hfld, &xfs_agfl_buf_ops },
+ { TYP_ATTR, "attr3", handle_struct, attr3_hfld, NULL },
+ { TYP_BMAPBTA, "bmapbta", handle_struct, bmapbta_crc_hfld,
+ &xfs_bmbt_buf_ops },
+ { TYP_BMAPBTD, "bmapbtd", handle_struct, bmapbtd_crc_hfld,
+ &xfs_bmbt_buf_ops },
+ { TYP_BNOBT, "bnobt", handle_struct, bnobt_crc_hfld,
+ &xfs_allocbt_buf_ops },
+ { TYP_CNTBT, "cntbt", handle_struct, cntbt_crc_hfld,
+ &xfs_allocbt_buf_ops },
+ { TYP_DATA, "data", handle_block, NULL, NULL },
+ { TYP_DIR2, "dir3", handle_struct, dir3_hfld, NULL },
+ { TYP_DQBLK, "dqblk", handle_struct, dqblk_hfld,
+ &xfs_dquot_buf_ops },
+ { TYP_INOBT, "inobt", handle_struct, inobt_crc_hfld,
+ &xfs_inobt_buf_ops },
+ { TYP_INODATA, "inodata", NULL, NULL, NULL },
+ { TYP_INODE, "inode", handle_struct, inode_crc_hfld,
+ &xfs_inode_buf_ops },
+ { TYP_LOG, "log", NULL, NULL, NULL },
+ { TYP_RTBITMAP, "rtbitmap", NULL, NULL, NULL },
+ { TYP_RTSUMMARY, "rtsummary", NULL, NULL, NULL },
+ { TYP_SB, "sb", handle_struct, sb_hfld, &xfs_sb_buf_ops },
+ { TYP_SYMLINK, "symlink", handle_struct, symlink_crc_hfld,
+ &xfs_symlink_buf_ops },
+ { TYP_TEXT, "text", handle_text, NULL, NULL },
{ TYP_NONE, NULL }
};
diff --git a/db/type.h b/db/type.h
index c41aca4d..3bb26f1 100644
--- a/db/type.h
+++ b/db/type.h
@@ -42,6 +42,7 @@ typedef struct typ
char *name;
pfunc_t pfunc;
const struct field *fields;
+ const struct xfs_buf_ops *bops;
} typ_t;
extern const typ_t *typtab, *cur_typ;
--
1.8.3.2
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 21/32] db: indicate if the CRC on a buffer is correct or not
[not found] <1380510944-8571-1-git-send-email-david@fromorbit.com>
` (19 preceding siblings ...)
2013-09-30 3:15 ` [PATCH 20/32] db: introduce verifier support into set_cur Dave Chinner
@ 2013-09-30 3:15 ` Dave Chinner
2013-09-30 3:15 ` [PATCH 22/32] db: verify and calculate inode CRCs Dave Chinner
` (10 subsequent siblings)
31 siblings, 0 replies; 56+ messages in thread
From: Dave Chinner @ 2013-09-30 3:15 UTC (permalink / raw)
To: xfs
From: Dave Chinner <dchinner@redhat.com>
When dumping metadata that has a CRC in it, output not only the CRC
but text to tell us whether the value is correct or not. Hence we
can see at a glance if there's something wrong or not.
Do this by peeking at the buffer attached to the current IO
contexted. If there was a CRC error, then it will be marked with a
EFSCORRUPTED error. Use this to determine what to output.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
db/agf.c | 2 +-
db/agfl.c | 2 +-
db/agi.c | 2 +-
db/btblock.c | 10 +++++-----
db/dir2.c | 4 ++--
db/dquot.c | 2 +-
db/field.c | 5 +++++
db/field.h | 4 ++++
db/fprint.c | 39 +++++++++++++++++++++++++++++++++++++++
db/fprint.h | 2 ++
db/inode.c | 2 +-
db/io.h | 6 ++++++
db/sb.c | 2 +-
db/symlink.c | 2 +-
14 files changed, 70 insertions(+), 14 deletions(-)
diff --git a/db/agf.c b/db/agf.c
index 389cb43..d9a07ca 100644
--- a/db/agf.c
+++ b/db/agf.c
@@ -71,7 +71,7 @@ const field_t agf_flds[] = {
{ "btreeblks", FLDT_UINT32D, OI(OFF(btreeblks)), C1, 0, TYP_NONE },
{ "uuid", FLDT_UUID, OI(OFF(uuid)), C1, 0, TYP_NONE },
{ "lsn", FLDT_UINT64X, OI(OFF(lsn)), C1, 0, TYP_NONE },
- { "crc", FLDT_UINT32X, OI(OFF(crc)), C1, 0, TYP_NONE },
+ { "crc", FLDT_CRC, OI(OFF(crc)), C1, 0, TYP_NONE },
{ NULL }
};
diff --git a/db/agfl.c b/db/agfl.c
index e2340e6..b29538f 100644
--- a/db/agfl.c
+++ b/db/agfl.c
@@ -58,7 +58,7 @@ const field_t agfl_crc_flds[] = {
{ "seqno", FLDT_AGNUMBER, OI(OFF(seqno)), C1, 0, TYP_NONE },
{ "uuid", FLDT_UUID, OI(OFF(uuid)), C1, 0, TYP_NONE },
{ "lsn", FLDT_UINT64X, OI(OFF(lsn)), C1, 0, TYP_NONE },
- { "crc", FLDT_UINT32X, OI(OFF(crc)), C1, 0, TYP_NONE },
+ { "crc", FLDT_CRC, OI(OFF(crc)), C1, 0, TYP_NONE },
{ "bno", FLDT_AGBLOCKNZ, OI(OFF(bno)), agfl_bno_size,
FLD_ARRAY|FLD_COUNT, TYP_DATA },
{ NULL }
diff --git a/db/agi.c b/db/agi.c
index 6b2e889..398bdbb 100644
--- a/db/agi.c
+++ b/db/agi.c
@@ -56,7 +56,7 @@ const field_t agi_flds[] = {
CI(XFS_AGI_UNLINKED_BUCKETS), FLD_ARRAY, TYP_NONE },
{ "uuid", FLDT_UUID, OI(OFF(uuid)), C1, 0, TYP_NONE },
{ "lsn", FLDT_UINT64X, OI(OFF(lsn)), C1, 0, TYP_NONE },
- { "crc", FLDT_UINT32X, OI(OFF(crc)), C1, 0, TYP_NONE },
+ { "crc", FLDT_CRC, OI(OFF(crc)), C1, 0, TYP_NONE },
{ NULL }
};
diff --git a/db/btblock.c b/db/btblock.c
index 34188db..1ea0cff 100644
--- a/db/btblock.c
+++ b/db/btblock.c
@@ -295,7 +295,7 @@ const field_t bmapbta_crc_flds[] = {
{ "lsn", FLDT_UINT64X, OI(OFF(u.l.bb_lsn)), C1, 0, TYP_NONE },
{ "uuid", FLDT_UUID, OI(OFF(u.l.bb_uuid)), C1, 0, TYP_NONE },
{ "owner", FLDT_INO, OI(OFF(u.l.bb_owner)), C1, 0, TYP_NONE },
- { "crc", FLDT_UINT32X, OI(OFF(u.l.bb_crc)), C1, 0, TYP_NONE },
+ { "crc", FLDT_CRC, OI(OFF(u.l.bb_crc)), C1, 0, TYP_NONE },
{ "recs", FLDT_BMAPBTAREC, btblock_rec_offset, btblock_rec_count,
FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE },
{ "keys", FLDT_BMAPBTAKEY, btblock_key_offset, btblock_key_count,
@@ -314,7 +314,7 @@ const field_t bmapbtd_crc_flds[] = {
{ "lsn", FLDT_UINT64X, OI(OFF(u.l.bb_lsn)), C1, 0, TYP_NONE },
{ "uuid", FLDT_UUID, OI(OFF(u.l.bb_uuid)), C1, 0, TYP_NONE },
{ "owner", FLDT_INO, OI(OFF(u.l.bb_owner)), C1, 0, TYP_NONE },
- { "crc", FLDT_UINT32X, OI(OFF(u.l.bb_crc)), C1, 0, TYP_NONE },
+ { "crc", FLDT_CRC, OI(OFF(u.l.bb_crc)), C1, 0, TYP_NONE },
{ "recs", FLDT_BMAPBTDREC, btblock_rec_offset, btblock_rec_count,
FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE },
{ "keys", FLDT_BMAPBTDKEY, btblock_key_offset, btblock_key_count,
@@ -405,7 +405,7 @@ const field_t inobt_crc_flds[] = {
{ "lsn", FLDT_UINT64X, OI(OFF(u.s.bb_lsn)), C1, 0, TYP_NONE },
{ "uuid", FLDT_UUID, OI(OFF(u.s.bb_uuid)), C1, 0, TYP_NONE },
{ "owner", FLDT_AGNUMBER, OI(OFF(u.s.bb_owner)), C1, 0, TYP_NONE },
- { "crc", FLDT_UINT32X, OI(OFF(u.s.bb_crc)), C1, 0, TYP_NONE },
+ { "crc", FLDT_CRC, OI(OFF(u.s.bb_crc)), C1, 0, TYP_NONE },
{ "recs", FLDT_INOBTREC, btblock_rec_offset, btblock_rec_count,
FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE },
{ "keys", FLDT_INOBTKEY, btblock_key_offset, btblock_key_count,
@@ -471,7 +471,7 @@ const field_t bnobt_crc_flds[] = {
{ "lsn", FLDT_UINT64X, OI(OFF(u.s.bb_lsn)), C1, 0, TYP_NONE },
{ "uuid", FLDT_UUID, OI(OFF(u.s.bb_uuid)), C1, 0, TYP_NONE },
{ "owner", FLDT_AGNUMBER, OI(OFF(u.s.bb_owner)), C1, 0, TYP_NONE },
- { "crc", FLDT_UINT32X, OI(OFF(u.s.bb_crc)), C1, 0, TYP_NONE },
+ { "crc", FLDT_CRC, OI(OFF(u.s.bb_crc)), C1, 0, TYP_NONE },
{ "recs", FLDT_BNOBTREC, btblock_rec_offset, btblock_rec_count,
FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE },
{ "keys", FLDT_BNOBTKEY, btblock_key_offset, btblock_key_count,
@@ -533,7 +533,7 @@ const field_t cntbt_crc_flds[] = {
{ "lsn", FLDT_UINT64X, OI(OFF(u.s.bb_lsn)), C1, 0, TYP_NONE },
{ "uuid", FLDT_UUID, OI(OFF(u.s.bb_uuid)), C1, 0, TYP_NONE },
{ "owner", FLDT_AGNUMBER, OI(OFF(u.s.bb_owner)), C1, 0, TYP_NONE },
- { "crc", FLDT_UINT32X, OI(OFF(u.s.bb_crc)), C1, 0, TYP_NONE },
+ { "crc", FLDT_CRC, OI(OFF(u.s.bb_crc)), C1, 0, TYP_NONE },
{ "recs", FLDT_CNTBTREC, btblock_rec_offset, btblock_rec_count,
FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE },
{ "keys", FLDT_CNTBTKEY, btblock_key_offset, btblock_key_count,
diff --git a/db/dir2.c b/db/dir2.c
index 8b08d48..2ec64e0 100644
--- a/db/dir2.c
+++ b/db/dir2.c
@@ -922,7 +922,7 @@ const field_t dir3_data_union_flds[] = {
#define DBH3OFF(f) bitize(offsetof(struct xfs_dir3_blk_hdr, f))
const field_t dir3_blkhdr_flds[] = {
{ "magic", FLDT_UINT32X, OI(DBH3OFF(magic)), C1, 0, TYP_NONE },
- { "crc", FLDT_UINT32X, OI(DBH3OFF(crc)), C1, 0, TYP_NONE },
+ { "crc", FLDT_CRC, OI(DBH3OFF(crc)), C1, 0, TYP_NONE },
{ "bno", FLDT_DFSBNO, OI(DBH3OFF(blkno)), C1, 0, TYP_BMAPBTD },
{ "lsn", FLDT_UINT64X, OI(DBH3OFF(lsn)), C1, 0, TYP_NONE },
{ "uuid", FLDT_UUID, OI(DBH3OFF(uuid)), C1, 0, TYP_NONE },
@@ -959,7 +959,7 @@ const field_t dir3_free_hdr_flds[] = {
#define DB3OFF(f) bitize(offsetof(struct xfs_da3_blkinfo, f))
const field_t da3_blkinfo_flds[] = {
{ "hdr", FLDT_DA_BLKINFO, OI(DB3OFF(hdr)), C1, 0, TYP_NONE },
- { "crc", FLDT_UINT32X, OI(DB3OFF(crc)), C1, 0, TYP_NONE },
+ { "crc", FLDT_CRC, OI(DB3OFF(crc)), C1, 0, TYP_NONE },
{ "bno", FLDT_DFSBNO, OI(DB3OFF(blkno)), C1, 0, TYP_BMAPBTD },
{ "lsn", FLDT_UINT64X, OI(DB3OFF(lsn)), C1, 0, TYP_NONE },
{ "uuid", FLDT_UUID, OI(DB3OFF(uuid)), C1, 0, TYP_NONE },
diff --git a/db/dquot.c b/db/dquot.c
index 6927956..2f7d463 100644
--- a/db/dquot.c
+++ b/db/dquot.c
@@ -48,7 +48,7 @@ const field_t dqblk_flds[] = {
{ "diskdq", FLDT_DISK_DQUOT, OI(DDOFF(diskdq)), C1, 0, TYP_NONE },
{ "fill", FLDT_CHARS, OI(DDOFF(fill)), CI(DDSZC(fill)), FLD_SKIPALL,
TYP_NONE },
- { "crc", FLDT_UINT32X, OI(DDOFF(crc)), C1, 0, TYP_NONE },
+ { "crc", FLDT_CRC, OI(DDOFF(crc)), C1, 0, TYP_NONE },
{ "lsn", FLDT_UINT64X, OI(DDOFF(lsn)), C1, 0, TYP_NONE },
{ "uuid", FLDT_UUID, OI(DDOFF(uuid)), C1, 0, TYP_NONE },
{ NULL }
diff --git a/db/field.c b/db/field.c
index c6d7404..4582097 100644
--- a/db/field.c
+++ b/db/field.c
@@ -163,6 +163,11 @@ const ftattr_t ftattrtab[] = {
0, fa_agblock, NULL },
{ FLDT_CNTBTREC, "cntbtrec", fp_sarray, (char *)cntbt_rec_flds,
SI(bitsz(xfs_alloc_rec_t)), 0, NULL, cntbt_rec_flds },
+
+/* CRC field */
+ { FLDT_CRC, "crc", fp_crc, "%#x (%s)", SI(bitsz(__uint32_t)),
+ 0, NULL, NULL },
+
{ FLDT_DEV, "dev", fp_num, "%#x", SI(bitsz(xfs_dev_t)), 0, NULL, NULL },
{ FLDT_DFILOFFA, "dfiloffa", fp_num, "%llu", SI(bitsz(xfs_dfiloff_t)),
0, fa_dfiloffa, NULL },
diff --git a/db/field.h b/db/field.h
index aecdf9f..6343c9a 100644
--- a/db/field.h
+++ b/db/field.h
@@ -80,6 +80,10 @@ typedef enum fldt {
FLDT_CNTBTKEY,
FLDT_CNTBTPTR,
FLDT_CNTBTREC,
+
+ /* CRC field type */
+ FLDT_CRC,
+
FLDT_DEV,
FLDT_DFILOFFA,
FLDT_DFILOFFD,
diff --git a/db/fprint.c b/db/fprint.c
index 1d2f29c..435d984 100644
--- a/db/fprint.c
+++ b/db/fprint.c
@@ -30,6 +30,7 @@
#include "output.h"
#include "sig.h"
#include "malloc.h"
+#include "io.h"
int
fp_charns(
@@ -184,3 +185,41 @@ fp_uuid(
}
return 1;
}
+
+/*
+ * CRC is correct is the current buffer it is being pulled out
+ * of is not marked with a EFSCORRUPTED error.
+ */
+int
+fp_crc(
+ void *obj,
+ int bit,
+ int count,
+ char *fmtstr,
+ int size,
+ int arg,
+ int base,
+ int array)
+{
+ int bitpos;
+ int i;
+ __int64_t val;
+ char *ok;
+
+ ok = iocur_crc_valid() ? "correct" : "bad";
+
+ for (i = 0, bitpos = bit;
+ i < count && !seenint();
+ i++, bitpos += size) {
+ if (array)
+ dbprintf("%d:", i + base);
+ val = getbitval(obj, bitpos, size, BVUNSIGNED);
+ if (size > 32)
+ dbprintf(fmtstr, val, ok);
+ else
+ dbprintf(fmtstr, (__int32_t)val, ok);
+ if (i < count - 1)
+ dbprintf(" ");
+ }
+ return 1;
+}
diff --git a/db/fprint.h b/db/fprint.h
index b032dbd..6a6d77e 100644
--- a/db/fprint.h
+++ b/db/fprint.h
@@ -29,3 +29,5 @@ extern int fp_time(void *obj, int bit, int count, char *fmtstr, int size,
int arg, int base, int array);
extern int fp_uuid(void *obj, int bit, int count, char *fmtstr, int size,
int arg, int base, int array);
+extern int fp_crc(void *obj, int bit, int count, char *fmtstr, int size,
+ int arg, int base, int array);
diff --git a/db/inode.c b/db/inode.c
index 634dc30..ec533ee 100644
--- a/db/inode.c
+++ b/db/inode.c
@@ -168,7 +168,7 @@ const field_t inode_core_flds[] = {
};
const field_t inode_v3_flds[] = {
- { "crc", FLDT_UINT32X, OI(COFF(crc)), C1, 0, TYP_NONE },
+ { "crc", FLDT_CRC, OI(COFF(crc)), C1, 0, TYP_NONE },
{ "change_count", FLDT_UINT64D, OI(COFF(changecount)), C1, 0, TYP_NONE },
{ "lsn", FLDT_UINT64X, OI(COFF(lsn)), C1, 0, TYP_NONE },
{ "flags2", FLDT_UINT64X, OI(COFF(flags2)), C1, 0, TYP_NONE },
diff --git a/db/io.h b/db/io.h
index 2c47ccc..d647284 100644
--- a/db/io.h
+++ b/db/io.h
@@ -58,3 +58,9 @@ extern void write_cur(void);
extern void set_cur(const struct typ *t, __int64_t d, int c, int ring_add,
bbmap_t *bbmap);
extern void ring_add(void);
+
+static inline bool
+iocur_crc_valid()
+{
+ return (iocur_top->bp && iocur_top->bp->b_error != EFSCORRUPTED);
+}
diff --git a/db/sb.c b/db/sb.c
index d178f58..b36abf8 100644
--- a/db/sb.c
+++ b/db/sb.c
@@ -118,7 +118,7 @@ const field_t sb_flds[] = {
C1, 0, TYP_NONE },
{ "features_log_incompat", FLDT_UINT32X, OI(OFF(features_log_incompat)),
C1, 0, TYP_NONE },
- { "crc", FLDT_UINT32X, OI(OFF(crc)), C1, 0, TYP_NONE },
+ { "crc", FLDT_CRC, OI(OFF(crc)), C1, 0, TYP_NONE },
{ "pquotino", FLDT_INO, OI(OFF(pquotino)), C1, 0, TYP_INODE },
{ "lsn", FLDT_UINT64X, OI(OFF(lsn)), C1, 0, TYP_NONE },
{ NULL }
diff --git a/db/symlink.c b/db/symlink.c
index 9f3d0b9..a4f420f 100644
--- a/db/symlink.c
+++ b/db/symlink.c
@@ -69,7 +69,7 @@ const struct field symlink_crc_flds[] = {
{ "magic", FLDT_UINT32X, OI(OFF(magic)), C1, 0, TYP_NONE },
{ "offset", FLDT_UINT32D, OI(OFF(offset)), C1, 0, TYP_NONE },
{ "bytes", FLDT_UINT32D, OI(OFF(bytes)), C1, 0, TYP_NONE },
- { "crc", FLDT_UINT32X, OI(OFF(crc)), C1, 0, TYP_NONE },
+ { "crc", FLDT_CRC, OI(OFF(crc)), C1, 0, TYP_NONE },
{ "uuid", FLDT_UUID, OI(OFF(uuid)), C1, 0, TYP_NONE },
{ "owner", FLDT_INO, OI(OFF(owner)), C1, 0, TYP_NONE },
{ "bno", FLDT_DFSBNO, OI(OFF(blkno)), C1, 0, TYP_BMAPBTD },
--
1.8.3.2
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 22/32] db: verify and calculate inode CRCs
[not found] <1380510944-8571-1-git-send-email-david@fromorbit.com>
` (20 preceding siblings ...)
2013-09-30 3:15 ` [PATCH 21/32] db: indicate if the CRC on a buffer is correct or not Dave Chinner
@ 2013-09-30 3:15 ` Dave Chinner
2013-09-30 3:15 ` [PATCH 23/32] db: verify and calculate dquot CRCs Dave Chinner
` (9 subsequent siblings)
31 siblings, 0 replies; 56+ messages in thread
From: Dave Chinner @ 2013-09-30 3:15 UTC (permalink / raw)
To: xfs
From: Dave Chinner <dchinner@redhat.com>
When we set the current Io cursor to point at an inode, verify that
the inode CRC is intact. And prior to writing such an IO cursor,
calculate the inode CRC.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
db/inode.c | 2 ++
db/io.c | 4 ++++
db/io.h | 6 +++++-
include/libxfs.h | 4 ++++
libxfs/xfs_inode_buf.c | 8 ++++----
5 files changed, 19 insertions(+), 5 deletions(-)
diff --git a/db/inode.c b/db/inode.c
index ec533ee..4090855 100644
--- a/db/inode.c
+++ b/db/inode.c
@@ -655,6 +655,8 @@ set_cur_inode(
blkbb, DB_RING_IGN, NULL);
off_cur(offset << mp->m_sb.sb_inodelog, mp->m_sb.sb_inodesize);
dip = iocur_top->data;
+ iocur_top->ino_crc_ok = libxfs_dinode_verify(mp, ino, dip);
+ iocur_top->ino_buf = 1;
iocur_top->ino = ino;
iocur_top->mode = be16_to_cpu(dip->di_mode);
if ((iocur_top->mode & S_IFMT) == S_IFDIR)
diff --git a/db/io.c b/db/io.c
index c9452f2..8ddb5e5 100644
--- a/db/io.c
+++ b/db/io.c
@@ -462,6 +462,9 @@ write_cur(void)
return;
}
+ if (iocur_top->ino_buf)
+ libxfs_dinode_calc_crc(mp, iocur_top->data);
+
if (iocur_top->bbmap)
write_cur_bbs();
else
@@ -534,6 +537,7 @@ set_cur(
iocur_top->ino = ino;
iocur_top->dirino = dirino;
iocur_top->mode = mode;
+ iocur_top->ino_buf = 0;
/* store location in ring */
if (ring_flag)
diff --git a/db/io.h b/db/io.h
index d647284..1f8270d 100644
--- a/db/io.h
+++ b/db/io.h
@@ -38,6 +38,8 @@ typedef struct iocur {
const struct typ *typ; /* type of "data" */
bbmap_t *bbmap; /* map daddr if fragmented */
struct xfs_buf *bp; /* underlying buffer */
+ int ino_crc_ok:1;
+ int ino_buf:1;
} iocur_t;
#define DB_RING_ADD 1 /* add to ring on set_cur */
@@ -62,5 +64,7 @@ extern void ring_add(void);
static inline bool
iocur_crc_valid()
{
- return (iocur_top->bp && iocur_top->bp->b_error != EFSCORRUPTED);
+ return (iocur_top->bp &&
+ iocur_top->bp->b_error != EFSCORRUPTED &&
+ (!iocur_top->ino_buf || iocur_top->ino_crc_ok));
}
diff --git a/include/libxfs.h b/include/libxfs.h
index 08fd0b3..d28ac48 100644
--- a/include/libxfs.h
+++ b/include/libxfs.h
@@ -755,6 +755,10 @@ void xfs_dinode_from_disk(struct xfs_icdinode *,
#define libxfs_idata_realloc xfs_idata_realloc
#define libxfs_idestroy_fork xfs_idestroy_fork
+#define libxfs_dinode_verify xfs_dinode_verify
+bool xfs_dinode_verify(struct xfs_mount *mp, xfs_ino_t ino,
+ struct xfs_dinode *dip);
+
/* xfs_sb.h */
#define libxfs_mod_sb xfs_mod_sb
#define libxfs_sb_from_disk xfs_sb_from_disk
diff --git a/libxfs/xfs_inode_buf.c b/libxfs/xfs_inode_buf.c
index b796556..728ef71 100644
--- a/libxfs/xfs_inode_buf.c
+++ b/libxfs/xfs_inode_buf.c
@@ -276,10 +276,10 @@ xfs_dinode_to_disk(
}
}
-static bool
+bool
xfs_dinode_verify(
struct xfs_mount *mp,
- struct xfs_inode *ip,
+ xfs_ino_t ino,
struct xfs_dinode *dip)
{
if (dip->di_magic != cpu_to_be16(XFS_DINODE_MAGIC))
@@ -294,7 +294,7 @@ xfs_dinode_verify(
if (!xfs_verify_cksum((char *)dip, mp->m_sb.sb_inodesize,
offsetof(struct xfs_dinode, di_crc)))
return false;
- if (be64_to_cpu(dip->di_ino) != ip->i_ino)
+ if (be64_to_cpu(dip->di_ino) != ino)
return false;
if (!uuid_equal(&dip->di_uuid, &mp->m_sb.sb_uuid))
return false;
@@ -346,7 +346,7 @@ xfs_iread(
return error;
/* even unallocated inodes are verified */
- if (!xfs_dinode_verify(mp, ip, dip)) {
+ if (!xfs_dinode_verify(mp, ip->i_ino, dip)) {
xfs_alert(mp, "%s: validation failed for inode %lld failed",
__func__, ip->i_ino);
--
1.8.3.2
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 23/32] db: verify and calculate dquot CRCs
[not found] <1380510944-8571-1-git-send-email-david@fromorbit.com>
` (21 preceding siblings ...)
2013-09-30 3:15 ` [PATCH 22/32] db: verify and calculate inode CRCs Dave Chinner
@ 2013-09-30 3:15 ` Dave Chinner
2013-09-30 3:15 ` [PATCH 24/32] db: add a special directory buffer verifier Dave Chinner
` (8 subsequent siblings)
31 siblings, 0 replies; 56+ messages in thread
From: Dave Chinner @ 2013-09-30 3:15 UTC (permalink / raw)
To: xfs
When we set the current Io cursor to point at a dquot block, verify
that the dquot CRC is intact. And prior to writing such an IO
cursor, calculate the dquot CRC.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
db/io.c | 5 ++++-
db/io.h | 1 +
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/db/io.c b/db/io.c
index 8ddb5e5..7281148 100644
--- a/db/io.c
+++ b/db/io.c
@@ -464,7 +464,9 @@ write_cur(void)
if (iocur_top->ino_buf)
libxfs_dinode_calc_crc(mp, iocur_top->data);
-
+ if (iocur_top->dquot_buf)
+ xfs_update_cksum(iocur_top->data, sizeof(struct xfs_dqblk),
+ XFS_DQUOT_CRC_OFF);
if (iocur_top->bbmap)
write_cur_bbs();
else
@@ -538,6 +540,7 @@ set_cur(
iocur_top->dirino = dirino;
iocur_top->mode = mode;
iocur_top->ino_buf = 0;
+ iocur_top->dquot_buf = 0;
/* store location in ring */
if (ring_flag)
diff --git a/db/io.h b/db/io.h
index 1f8270d..4f24c83 100644
--- a/db/io.h
+++ b/db/io.h
@@ -40,6 +40,7 @@ typedef struct iocur {
struct xfs_buf *bp; /* underlying buffer */
int ino_crc_ok:1;
int ino_buf:1;
+ int dquot_buf:1;
} iocur_t;
#define DB_RING_ADD 1 /* add to ring on set_cur */
--
1.8.3.2
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 24/32] db: add a special directory buffer verifier
[not found] <1380510944-8571-1-git-send-email-david@fromorbit.com>
` (22 preceding siblings ...)
2013-09-30 3:15 ` [PATCH 23/32] db: verify and calculate dquot CRCs Dave Chinner
@ 2013-09-30 3:15 ` Dave Chinner
2013-09-30 3:15 ` [PATCH 25/32] db: add a special attribute " Dave Chinner
` (7 subsequent siblings)
31 siblings, 0 replies; 56+ messages in thread
From: Dave Chinner @ 2013-09-30 3:15 UTC (permalink / raw)
To: xfs
From: Dave Chinner <dchinner@redhat.com>
Because we only have a single directory type that is used for all
the different buffer types, we need to provide a special verifier
for the read code. That verifier needs to know all the directory
types and when it find one it knows about, switch to the correct
verifier and call it.
We already do this for certain readahead cases in the directory
code, so there is precedence for this. If we don't find a magic
number we recognise, the verifier fails...
Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
db/dir2.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
db/dir2.h | 2 ++
db/type.c | 3 ++-
3 files changed, 65 insertions(+), 1 deletion(-)
diff --git a/db/dir2.c b/db/dir2.c
index 2ec64e0..5a10955 100644
--- a/db/dir2.c
+++ b/db/dir2.c
@@ -24,6 +24,7 @@
#include "field.h"
#include "dir2.h"
#include "init.h"
+#include "output.h"
static int dir2_block_hdr_count(void *obj, int startoff);
static int dir2_block_leaf_count(void *obj, int startoff);
@@ -975,3 +976,63 @@ const field_t da3_node_hdr_flds[] = {
{ "pad", FLDT_UINT32D, OI(H3OFF(__pad32)), C1, 0, TYP_NONE },
{ NULL }
};
+
+/*
+ * Special read verifier for directory buffers. detect the magic number
+ * appropriately and set the correct verifier and call it.
+ */
+static void
+xfs_dir3_db_read_verify(
+ struct xfs_buf *bp)
+{
+ __be32 magic32;
+ __be16 magic16;
+
+ magic32 = *(__be32 *)bp->b_addr;
+ magic16 = ((struct xfs_da_blkinfo *)bp->b_addr)->magic;
+
+ switch (magic32) {
+ case cpu_to_be32(XFS_DIR3_BLOCK_MAGIC):
+ bp->b_ops = &xfs_dir3_block_buf_ops;
+ goto verify;
+ case cpu_to_be32(XFS_DIR3_DATA_MAGIC):
+ bp->b_ops = &xfs_dir3_data_buf_ops;
+ goto verify;
+ case cpu_to_be32(XFS_DIR3_FREE_MAGIC):
+ bp->b_ops = &xfs_dir3_free_buf_ops;
+ goto verify;
+ default:
+ break;
+ }
+
+ switch (magic16) {
+ case cpu_to_be16(XFS_DIR3_LEAF1_MAGIC):
+ bp->b_ops = &xfs_dir3_leaf1_buf_ops;
+ break;
+ case cpu_to_be16(XFS_DIR3_LEAFN_MAGIC):
+ bp->b_ops = &xfs_dir3_leafn_buf_ops;
+ break;
+ case cpu_to_be16(XFS_DA3_NODE_MAGIC):
+ bp->b_ops = &xfs_da3_node_buf_ops;
+ break;
+ default:
+ dbprintf(_("Unknown directory buffer type!\n"));
+ xfs_buf_ioerror(bp, EFSCORRUPTED);
+ return;
+ }
+verify:
+ bp->b_ops->verify_read(bp);
+}
+
+static void
+xfs_dir3_db_write_verify(
+ struct xfs_buf *bp)
+{
+ dbprintf(_("Writing unknown directory buffer type!\n"));
+ xfs_buf_ioerror(bp, EFSCORRUPTED);
+}
+
+const struct xfs_buf_ops xfs_dir3_db_buf_ops = {
+ .verify_read = xfs_dir3_db_read_verify,
+ .verify_write = xfs_dir3_db_write_verify,
+};
diff --git a/db/dir2.h b/db/dir2.h
index b3651d5..5054493 100644
--- a/db/dir2.h
+++ b/db/dir2.h
@@ -60,3 +60,5 @@ static inline xfs_dir2_inou_t *xfs_dir2_sf_inumberp(xfs_dir2_sf_entry_t *sfep)
extern int dir2_data_union_size(void *obj, int startoff, int idx);
extern int dir2_size(void *obj, int startoff, int idx);
+
+extern const struct xfs_buf_ops xfs_dir3_db_buf_ops;
diff --git a/db/type.c b/db/type.c
index b3f3d87..2c3431e 100644
--- a/db/type.c
+++ b/db/type.c
@@ -87,7 +87,8 @@ static const typ_t __typtab_crc[] = {
{ TYP_CNTBT, "cntbt", handle_struct, cntbt_crc_hfld,
&xfs_allocbt_buf_ops },
{ TYP_DATA, "data", handle_block, NULL, NULL },
- { TYP_DIR2, "dir3", handle_struct, dir3_hfld, NULL },
+ { TYP_DIR2, "dir3", handle_struct, dir3_hfld,
+ &xfs_dir3_db_buf_ops },
{ TYP_DQBLK, "dqblk", handle_struct, dqblk_hfld,
&xfs_dquot_buf_ops },
{ TYP_INOBT, "inobt", handle_struct, inobt_crc_hfld,
--
1.8.3.2
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 25/32] db: add a special attribute buffer verifier
[not found] <1380510944-8571-1-git-send-email-david@fromorbit.com>
` (23 preceding siblings ...)
2013-09-30 3:15 ` [PATCH 24/32] db: add a special directory buffer verifier Dave Chinner
@ 2013-09-30 3:15 ` Dave Chinner
2013-09-30 3:15 ` [PATCH 26/32] db: re-enable write support for v5 filesystems Dave Chinner
` (6 subsequent siblings)
31 siblings, 0 replies; 56+ messages in thread
From: Dave Chinner @ 2013-09-30 3:15 UTC (permalink / raw)
To: xfs
From: Dave Chinner <dchinner@redhat.com>
Because we only have a single attribute type that is used for all
the attribute buffer types, we need to provide a special verifier
for the read code. That verifier needs to know all the attribute
types and when it find one it knows about, switch to the correct
verifier and call it.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
db/attr.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
db/attr.h | 2 ++
db/type.c | 3 ++-
3 files changed, 55 insertions(+), 1 deletion(-)
diff --git a/db/attr.c b/db/attr.c
index cd95a0a..359af7b 100644
--- a/db/attr.c
+++ b/db/attr.c
@@ -25,6 +25,7 @@
#include "attr.h"
#include "io.h"
#include "init.h"
+#include "output.h"
static int attr_leaf_entries_count(void *obj, int startoff);
static int attr_leaf_hdr_count(void *obj, int startoff);
@@ -522,3 +523,53 @@ const field_t attr3_leaf_hdr_flds[] = {
{ NULL }
};
+/*
+ * Special read verifier for attribute buffers. detect the magic number
+ * appropriately and set the correct verifier and call it.
+ */
+static void
+xfs_attr3_db_read_verify(
+ struct xfs_buf *bp)
+{
+ __be32 magic32;
+ __be16 magic16;
+
+ magic32 = *(__be32 *)bp->b_addr;
+ magic16 = ((struct xfs_da_blkinfo *)bp->b_addr)->magic;
+
+ switch (magic16) {
+ case cpu_to_be16(XFS_ATTR3_LEAF_MAGIC):
+ bp->b_ops = &xfs_attr3_leaf_buf_ops;
+ goto verify;
+ case cpu_to_be16(XFS_DA3_NODE_MAGIC):
+ bp->b_ops = &xfs_da3_node_buf_ops;
+ goto verify;
+ default:
+ break;
+ }
+
+ switch (magic32) {
+ case cpu_to_be32(XFS_ATTR3_RMT_MAGIC):
+ bp->b_ops = &xfs_attr3_rmt_buf_ops;
+ break;
+ default:
+ dbprintf(_("Unknown attribute buffer type!\n"));
+ xfs_buf_ioerror(bp, EFSCORRUPTED);
+ return;
+ }
+verify:
+ bp->b_ops->verify_read(bp);
+}
+
+static void
+xfs_attr3_db_write_verify(
+ struct xfs_buf *bp)
+{
+ dbprintf(_("Writing unknown attribute buffer type!\n"));
+ xfs_buf_ioerror(bp, EFSCORRUPTED);
+}
+
+const struct xfs_buf_ops xfs_attr3_db_buf_ops = {
+ .verify_read = xfs_attr3_db_read_verify,
+ .verify_write = xfs_attr3_db_write_verify,
+};
diff --git a/db/attr.h b/db/attr.h
index 3065372..bc3431f 100644
--- a/db/attr.h
+++ b/db/attr.h
@@ -33,3 +33,5 @@ extern const field_t attr3_node_hdr_flds[];
extern int attr_leaf_name_size(void *obj, int startoff, int idx);
extern int attr_size(void *obj, int startoff, int idx);
+
+extern const struct xfs_buf_ops xfs_attr3_db_buf_ops;
diff --git a/db/type.c b/db/type.c
index 2c3431e..04d0d56 100644
--- a/db/type.c
+++ b/db/type.c
@@ -77,7 +77,8 @@ static const typ_t __typtab_crc[] = {
{ TYP_AGF, "agf", handle_struct, agf_hfld, &xfs_agf_buf_ops },
{ TYP_AGFL, "agfl", handle_struct, agfl_crc_hfld, &xfs_agfl_buf_ops },
{ TYP_AGI, "agi", handle_struct, agi_hfld, &xfs_agfl_buf_ops },
- { TYP_ATTR, "attr3", handle_struct, attr3_hfld, NULL },
+ { TYP_ATTR, "attr3", handle_struct, attr3_hfld,
+ &xfs_attr3_db_buf_ops },
{ TYP_BMAPBTA, "bmapbta", handle_struct, bmapbta_crc_hfld,
&xfs_bmbt_buf_ops },
{ TYP_BMAPBTD, "bmapbtd", handle_struct, bmapbtd_crc_hfld,
--
1.8.3.2
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 26/32] db: re-enable write support for v5 filesystems.
[not found] <1380510944-8571-1-git-send-email-david@fromorbit.com>
` (24 preceding siblings ...)
2013-09-30 3:15 ` [PATCH 25/32] db: add a special attribute " Dave Chinner
@ 2013-09-30 3:15 ` Dave Chinner
2013-09-30 3:15 ` [PATCH 27/32] libxfs: fix root inode handling inconsistencies Dave Chinner
` (5 subsequent siblings)
31 siblings, 0 replies; 56+ messages in thread
From: Dave Chinner @ 2013-09-30 3:15 UTC (permalink / raw)
To: xfs
From: Dave Chinner <dchinner@redhat.com>
As we can now verify and recalculate CRCs on IO, we can modify the
on-disk structures without corrupting the filesyste, This makes it
safe to turn write support on for v5 filesystems for the first time.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
db/init.c | 15 ---------------
1 file changed, 15 deletions(-)
diff --git a/db/init.c b/db/init.c
index b1cddca..a9b357b 100644
--- a/db/init.c
+++ b/db/init.c
@@ -143,21 +143,6 @@ init(
exit(EXIT_FAILURE);
}
- /*
- * Don't allow modifications to CRC enabled filesystems until we support
- * CRC recalculation in the IO path. Unless, of course, the user is in
- * the process of hitting us with a big hammer.
- */
- if (XFS_SB_VERSION_NUM(sbp) >= XFS_SB_VERSION_5 &&
- !(x.isreadonly & LIBXFS_ISREADONLY)) {
- fprintf(stderr,
- _("%s: modifications to %s are not supported in thi version.\n"
- "Use \"-r\" to run %s in read-only mode on this filesystem .\n"),
- progname, fsdevice, progname);
- if (!force)
- exit(EXIT_FAILURE);
- }
-
mp = libxfs_mount(&xmount, sbp, x.ddev, x.logdev, x.rtdev,
LIBXFS_MOUNT_ROOTINOS | LIBXFS_MOUNT_DEBUGGER);
if (!mp) {
--
1.8.3.2
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 27/32] libxfs: fix root inode handling inconsistencies
[not found] <1380510944-8571-1-git-send-email-david@fromorbit.com>
` (25 preceding siblings ...)
2013-09-30 3:15 ` [PATCH 26/32] db: re-enable write support for v5 filesystems Dave Chinner
@ 2013-09-30 3:15 ` Dave Chinner
2013-09-30 3:15 ` [PATCH 28/32] xfs_db: avoid libxfs buffer lookup warnings Dave Chinner
` (4 subsequent siblings)
31 siblings, 0 replies; 56+ messages in thread
From: Dave Chinner @ 2013-09-30 3:15 UTC (permalink / raw)
To: xfs
From: Dave Chinner <dchinner@redhat.com>
When "mounting" a filesystem via libxfs_mount(), callers can tell
libxfs to read the root and realtime inodes into cache. However,
when unmounting the filesystem, libxfs_unmount() used to
unconditionally free root inodes if they were present.
This leads to interesting issues like in mkfs, when it handles
creation, reading and freeing of the root and rt inodes itself.
It, however, passes in the flag to tell libxfs_mount() to read the
root inode, and so when unmounting throws an error like:
cache_node_put: node put on refcount 0 (node=0x684610)
When a second libxfs_iput() call is made on the root inode.
Clean this up and fix up all the callers that use magic numbers
rather than symbolic values to tell libxfs tomount the root inodes.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
copy/xfs_copy.c | 3 ++-
mkfs/xfs_mkfs.c | 3 ++-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/copy/xfs_copy.c b/copy/xfs_copy.c
index bb37279..b6695d7 100644
--- a/copy/xfs_copy.c
+++ b/copy/xfs_copy.c
@@ -684,7 +684,8 @@ main(int argc, char **argv)
sb = &mbuf.m_sb;
libxfs_sb_from_disk(sb, XFS_BUF_TO_SBP(sbp));
- mp = libxfs_mount(&mbuf, sb, xargs.ddev, xargs.logdev, xargs.rtdev, 1);
+ mp = libxfs_mount(&mbuf, sb, xargs.ddev, xargs.logdev, xargs.rtdev,
+ LIBXFS_MOUNT_ROOTINOS);
if (mp == NULL) {
do_log(_("%s: %s filesystem failed to initialize\n"
"%s: Aborting.\n"), progname, source_name, progname);
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index eafbed3..60e4d88 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -2556,6 +2556,7 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
memset(XFS_BUF_PTR(buf), 0, sectorsize);
libxfs_sb_to_disk((void *)XFS_BUF_PTR(buf), sbp, XFS_SB_ALL_BITS);
libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
+ libxfs_purgebuf(buf);
/*
* If the data area is a file, then grow it out to its final size
@@ -2590,7 +2591,7 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
(xfs_extlen_t)XFS_FSB_TO_BB(mp, logblocks),
&sbp->sb_uuid, logversion, lsunit, XLOG_FMT);
- mp = libxfs_mount(mp, sbp, xi.ddev, xi.logdev, xi.rtdev, 1);
+ mp = libxfs_mount(mp, sbp, xi.ddev, xi.logdev, xi.rtdev, 0);
if (mp == NULL) {
fprintf(stderr, _("%s: filesystem failed to initialize\n"),
progname);
--
1.8.3.2
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 28/32] xfs_db: avoid libxfs buffer lookup warnings
[not found] <1380510944-8571-1-git-send-email-david@fromorbit.com>
` (26 preceding siblings ...)
2013-09-30 3:15 ` [PATCH 27/32] libxfs: fix root inode handling inconsistencies Dave Chinner
@ 2013-09-30 3:15 ` Dave Chinner
2013-09-30 3:15 ` [PATCH 29/32] libxfs: work around do_div() not handling 32 bit numerators Dave Chinner
` (3 subsequent siblings)
31 siblings, 0 replies; 56+ messages in thread
From: Dave Chinner @ 2013-09-30 3:15 UTC (permalink / raw)
To: xfs
From: Dave Chinner <dchinner@redhat.com>
When we mount the filesystem inside xfs_db, libxfs is tasked with
reading some information from disk, such as root inodes. Because
libxfs does this inode reading, it uses inode cluster buffers to
read the inodes. xfs_db, OTOH, just uses FSB sized buffers to read
inodes, and hence xfs_db throws a warning when reading the root
inode block like so:
$ sudo xfs_db -c "sb 0" -c "p rootino" -c "inode 32" /dev/vda
Version 5 superblock detected. xfsprogs has EXPERIMENTAL support enabled!
Use of these features is at your own risk!
rootino = 32
7f59f20e6740: Badness in key lookup (length)
bp=(bno 0x20, len 8192 bytes) key=(bno 0x20, len 1024 bytes)
$
There is another way this can happen, and that is dumping raw data
from disk using either the "fsb NNN" or "daddr MMM" commands to dump
untyped information. This is always read in sector or filesystem
block units, and so will cause similar badness warnings.
xfs_db is unique in the way it can read the same blocks with
different lengths, so we really need a way to avoid having duplicate
buffers in the cache. To handle this in a generic way, introduce a
"purge on compare failure" feature to libxfs.
What this feature does is instead of throwing a warning when a
buffer miscompare occurs (e.g. due to a length mismatch), it purges
the buffer that is in cache from the cache. We can do this safely in
the context of xfs_db because it always writes back changes made to
buffers before it releases the reference to the buffer. Hence we can
purge buffers directly from the lookup code without having to worry
about whether they are dirty or not.
Doing this purge on miscompare operation avoids the
problem that libxfs is currently warning about, and hence if the
feature flag is set then we don't need to warn about miscompares any
more. Hence the whole problem goes away entirely for xfs_db, without
affecting any of the other users of libxfs based IO.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
db/init.c | 1 +
db/inode.c | 33 +++++++++++++++++++--
db/io.c | 4 ++-
include/cache.h | 22 +++++++++++++-
include/libxfs.h | 2 ++
libxfs/cache.c | 83 +++++++++++++++++++++++++++++++++++++++--------------
libxfs/init.c | 6 ++--
libxfs/rdwr.c | 30 ++++++++++---------
repair/xfs_repair.c | 4 +--
9 files changed, 143 insertions(+), 42 deletions(-)
diff --git a/db/init.c b/db/init.c
index a9b357b..2b643f9 100644
--- a/db/init.c
+++ b/db/init.c
@@ -109,6 +109,7 @@ init(
else
x.dname = fsdevice;
+ x.bcache_flags = CACHE_MISCOMPARE_PURGE;
if (!libxfs_init(&x)) {
fputs(_("\nfatal error -- couldn't initialize XFS library\n"),
stderr);
diff --git a/db/inode.c b/db/inode.c
index 4090855..24170ba 100644
--- a/db/inode.c
+++ b/db/inode.c
@@ -623,6 +623,14 @@ inode_u_symlink_count(
(int)be64_to_cpu(dip->di_size) : 0;
}
+/*
+ * We are now using libxfs for our IO backend, so we should always try to use
+ * inode cluster buffers rather than filesystem block sized buffers for reading
+ * inodes. This means that we always use the same buffers as libxfs operations
+ * does, and that avoids buffer cache issues caused by overlapping buffers. This
+ * can be seen clearly when trying to read the root inode. Much of this logic is
+ * similar to libxfs_imap().
+ */
void
set_cur_inode(
xfs_ino_t ino)
@@ -632,6 +640,9 @@ set_cur_inode(
xfs_agnumber_t agno;
xfs_dinode_t *dip;
int offset;
+ int numblks = blkbb;
+ xfs_agblock_t cluster_agbno;
+
agno = XFS_INO_TO_AGNO(mp, ino);
agino = XFS_INO_TO_AGINO(mp, ino);
@@ -644,6 +655,24 @@ set_cur_inode(
return;
}
cur_agno = agno;
+
+ if (mp->m_inode_cluster_size > mp->m_sb.sb_blocksize &&
+ mp->m_inoalign_mask) {
+ xfs_agblock_t chunk_agbno;
+ xfs_agblock_t offset_agbno;
+ int blks_per_cluster;
+
+ blks_per_cluster = mp->m_inode_cluster_size >>
+ mp->m_sb.sb_blocklog;
+ offset_agbno = agbno & mp->m_inoalign_mask;
+ chunk_agbno = agbno - offset_agbno;
+ cluster_agbno = chunk_agbno +
+ ((offset_agbno / blks_per_cluster) * blks_per_cluster);
+ offset += ((agbno - cluster_agbno) * mp->m_sb.sb_inopblock);
+ numblks = XFS_FSB_TO_BB(mp, blks_per_cluster);
+ } else
+ cluster_agbno = agbno;
+
/*
* First set_cur to the block with the inode
* then use off_cur to get the right part of the buffer.
@@ -651,8 +680,8 @@ set_cur_inode(
ASSERT(typtab[TYP_INODE].typnm == TYP_INODE);
/* ingore ring update here, do it explicitly below */
- set_cur(&typtab[TYP_INODE], XFS_AGB_TO_DADDR(mp, agno, agbno),
- blkbb, DB_RING_IGN, NULL);
+ set_cur(&typtab[TYP_INODE], XFS_AGB_TO_DADDR(mp, agno, cluster_agbno),
+ numblks, DB_RING_IGN, NULL);
off_cur(offset << mp->m_sb.sb_inodelog, mp->m_sb.sb_inodesize);
dip = iocur_top->data;
iocur_top->ino_crc_ok = libxfs_dinode_verify(mp, ino, dip);
diff --git a/db/io.c b/db/io.c
index 7281148..123214d 100644
--- a/db/io.c
+++ b/db/io.c
@@ -104,8 +104,10 @@ pop_cur(void)
dbprintf(_("can't pop anything from I/O stack\n"));
return;
}
- if (iocur_top->bp)
+ if (iocur_top->bp) {
libxfs_putbuf(iocur_top->bp);
+ iocur_top->bp = NULL;
+ }
if (iocur_top->bbmap) {
free(iocur_top->bbmap);
iocur_top->bbmap = NULL;
diff --git a/include/cache.h b/include/cache.h
index 0c0a1c5..c5757d0 100644
--- a/include/cache.h
+++ b/include/cache.h
@@ -18,6 +18,25 @@
#ifndef __CACHE_H__
#define __CACHE_H__
+/*
+ * initialisation flags
+ */
+/*
+ * xfs_db always writes changes immediately, and so we need to purge buffers
+ * when we get a buffer lookup mismatch due to readin the same block with a
+ * different buffer configuration.
+ */
+#define CACHE_MISCOMPARE_PURGE (1 << 0)
+
+/*
+ * cache object campare return values
+ */
+enum {
+ CACHE_HIT,
+ CACHE_MISS,
+ CACHE_PURGE,
+};
+
#define HASH_CACHE_RATIO 8
/*
@@ -82,6 +101,7 @@ struct cache_node {
};
struct cache {
+ int c_flags; /* behavioural flags */
unsigned int c_maxcount; /* max cache nodes */
unsigned int c_count; /* count of nodes */
pthread_mutex_t c_mutex; /* node count mutex */
@@ -99,7 +119,7 @@ struct cache {
unsigned int c_max; /* max nodes ever used */
};
-struct cache *cache_init(unsigned int, struct cache_operations *);
+struct cache *cache_init(int, unsigned int, struct cache_operations *);
void cache_destroy(struct cache *);
void cache_walk(struct cache *, cache_walk_t);
void cache_purge(struct cache *);
diff --git a/include/libxfs.h b/include/libxfs.h
index d28ac48..049b217 100644
--- a/include/libxfs.h
+++ b/include/libxfs.h
@@ -110,6 +110,8 @@ typedef struct {
int dfd; /* data subvolume file descriptor */
int logfd; /* log subvolume file descriptor */
int rtfd; /* realtime subvolume file descriptor */
+ int icache_flags; /* cache init flags */
+ int bcache_flags; /* cache init flags */
} libxfs_init_t;
#define LIBXFS_EXIT_ON_FAILURE 0x0001 /* exit the program if a call fails */
diff --git a/libxfs/cache.c b/libxfs/cache.c
index 56b24e7..84d2860 100644
--- a/libxfs/cache.c
+++ b/libxfs/cache.c
@@ -38,6 +38,7 @@ static unsigned int cache_generic_bulkrelse(struct cache *, struct list_head *);
struct cache *
cache_init(
+ int flags,
unsigned int hashsize,
struct cache_operations *cache_operations)
{
@@ -53,6 +54,7 @@ cache_init(
return NULL;
}
+ cache->c_flags = flags;
cache->c_count = 0;
cache->c_max = 0;
cache->c_hits = 0;
@@ -289,6 +291,34 @@ cache_overflowed(
return (cache->c_maxcount == cache->c_max);
}
+
+static int
+__cache_node_purge(
+ struct cache * cache,
+ struct cache_node * node)
+{
+ int count;
+ struct cache_mru * mru;
+
+ pthread_mutex_lock(&node->cn_mutex);
+ count = node->cn_count;
+ if (count != 0) {
+ pthread_mutex_unlock(&node->cn_mutex);
+ return count;
+ }
+ mru = &cache->c_mrus[node->cn_priority];
+ pthread_mutex_lock(&mru->cm_mutex);
+ list_del_init(&node->cn_mru);
+ mru->cm_count--;
+ pthread_mutex_unlock(&mru->cm_mutex);
+
+ pthread_mutex_unlock(&node->cn_mutex);
+ pthread_mutex_destroy(&node->cn_mutex);
+ list_del_init(&node->cn_hash);
+ cache->relse(node);
+ return count;
+}
+
/*
* Lookup in the cache hash table. With any luck we'll get a cache
* hit, in which case this will all be over quickly and painlessly.
@@ -308,8 +338,10 @@ cache_node_get(
struct cache_mru * mru;
struct list_head * head;
struct list_head * pos;
+ struct list_head * n;
unsigned int hashidx;
int priority = 0;
+ int purged = 0;
hashidx = cache->hash(key, cache->c_hashsize);
hash = cache->c_hash + hashidx;
@@ -317,10 +349,26 @@ cache_node_get(
for (;;) {
pthread_mutex_lock(&hash->ch_mutex);
- for (pos = head->next; pos != head; pos = pos->next) {
+ for (pos = head->next, n = pos->next; pos != head;
+ pos = n, n = pos->next) {
+ int result;
+
node = list_entry(pos, struct cache_node, cn_hash);
- if (!cache->compare(node, key))
- continue;
+ result = cache->compare(node, key);
+ switch (result) {
+ case CACHE_HIT:
+ break;
+ case CACHE_PURGE:
+ if ((cache->c_flags & CACHE_MISCOMPARE_PURGE) &&
+ !__cache_node_purge(cache, node)) {
+ purged++;
+ hash->ch_count--;
+ }
+ /* FALL THROUGH */
+ case CACHE_MISS:
+ goto next_object;
+ }
+
/*
* node found, bump node's reference count, remove it
* from its MRU list, and update stats.
@@ -347,6 +395,8 @@ cache_node_get(
*nodep = node;
return 0;
+next_object:
+ continue; /* what the hell, gcc? */
}
pthread_mutex_unlock(&hash->ch_mutex);
/*
@@ -375,6 +425,12 @@ cache_node_get(
list_add(&node->cn_hash, &hash->ch_list);
pthread_mutex_unlock(&hash->ch_mutex);
+ if (purged) {
+ pthread_mutex_lock(&cache->c_mutex);
+ cache->c_count -= purged;
+ pthread_mutex_unlock(&cache->c_mutex);
+ }
+
*nodep = node;
return 1;
}
@@ -457,7 +513,6 @@ cache_node_purge(
struct list_head * pos;
struct list_head * n;
struct cache_hash * hash;
- struct cache_mru * mru;
int count = -1;
hash = cache->c_hash + cache->hash(key, cache->c_hashsize);
@@ -468,23 +523,9 @@ cache_node_purge(
if ((struct cache_node *)pos != node)
continue;
- pthread_mutex_lock(&node->cn_mutex);
- count = node->cn_count;
- if (count != 0) {
- pthread_mutex_unlock(&node->cn_mutex);
- break;
- }
- mru = &cache->c_mrus[node->cn_priority];
- pthread_mutex_lock(&mru->cm_mutex);
- list_del_init(&node->cn_mru);
- mru->cm_count--;
- pthread_mutex_unlock(&mru->cm_mutex);
-
- pthread_mutex_unlock(&node->cn_mutex);
- pthread_mutex_destroy(&node->cn_mutex);
- list_del_init(&node->cn_hash);
- hash->ch_count--;
- cache->relse(node);
+ count = __cache_node_purge(cache, node);
+ if (!count)
+ hash->ch_count--;
break;
}
pthread_mutex_unlock(&hash->ch_mutex);
diff --git a/libxfs/init.c b/libxfs/init.c
index 229aa50..637f29e 100644
--- a/libxfs/init.c
+++ b/libxfs/init.c
@@ -337,10 +337,12 @@ libxfs_init(libxfs_init_t *a)
chdir(curdir);
if (!libxfs_ihash_size)
libxfs_ihash_size = LIBXFS_IHASHSIZE(sbp);
- libxfs_icache = cache_init(libxfs_ihash_size, &libxfs_icache_operations);
+ libxfs_icache = cache_init(a->icache_flags, libxfs_ihash_size,
+ &libxfs_icache_operations);
if (!libxfs_bhash_size)
libxfs_bhash_size = LIBXFS_BHASHSIZE(sbp);
- libxfs_bcache = cache_init(libxfs_bhash_size, &libxfs_bcache_operations);
+ libxfs_bcache = cache_init(a->bcache_flags, libxfs_bhash_size,
+ &libxfs_bcache_operations);
use_xfs_buf_lock = a->usebuflock;
manage_zones(0);
rval = 1;
diff --git a/libxfs/rdwr.c b/libxfs/rdwr.c
index 8d8bcfc..6d6a915 100644
--- a/libxfs/rdwr.c
+++ b/libxfs/rdwr.c
@@ -323,20 +323,24 @@ libxfs_bcompare(struct cache_node *node, cache_key_t key)
struct xfs_buf *bp = (struct xfs_buf *)node;
struct xfs_bufkey *bkey = (struct xfs_bufkey *)key;
-#ifdef IO_BCOMPARE_CHECK
if (bp->b_target->dev == bkey->buftarg->dev &&
- bp->b_bn == bkey->blkno &&
- bp->b_bcount != BBTOB(bkey->bblen))
- fprintf(stderr, "%lx: Badness in key lookup (length)\n"
- "bp=(bno 0x%llx, len %u bytes) key=(bno 0x%llx, len %u bytes)\n",
- pthread_self(),
- (unsigned long long)bp->b_bn, (int)bp->b_bcount,
- (unsigned long long)bkey->blkno, BBTOB(bkey->bblen));
+ bp->b_bn == bkey->blkno) {
+ if (bp->b_bcount == BBTOB(bkey->bblen))
+ return CACHE_HIT;
+#ifdef IO_BCOMPARE_CHECK
+ if (!(libxfs_bcache->c_flags & CACHE_MISCOMPARE_PURGE)) {
+ fprintf(stderr,
+ "%lx: Badness in key lookup (length)\n"
+ "bp=(bno 0x%llx, len %u bytes) key=(bno 0x%llx, len %u bytes)\n",
+ pthread_self(),
+ (unsigned long long)bp->b_bn, (int)bp->b_bcount,
+ (unsigned long long)bkey->blkno,
+ BBTOB(bkey->bblen));
+ }
#endif
-
- return (bp->b_target->dev == bkey->buftarg->dev &&
- bp->b_bn == bkey->blkno &&
- bp->b_bcount == BBTOB(bkey->bblen));
+ return CACHE_PURGE;
+ }
+ return CACHE_MISS;
}
void
@@ -1029,7 +1033,7 @@ libxfs_icompare(struct cache_node *node, cache_key_t key)
{
xfs_inode_t *ip = (xfs_inode_t *)node;
- return (ip->i_ino == *(xfs_ino_t *)key);
+ return (ip->i_ino == *(xfs_ino_t *)key) ? CACHE_HIT : CACHE_MISS;
}
int
diff --git a/repair/xfs_repair.c b/repair/xfs_repair.c
index 820e7a2..55a451b 100644
--- a/repair/xfs_repair.c
+++ b/repair/xfs_repair.c
@@ -712,9 +712,9 @@ main(int argc, char **argv)
if (!ihash_option_used)
libxfs_ihash_size = libxfs_bhash_size;
- libxfs_icache = cache_init(libxfs_ihash_size,
+ libxfs_icache = cache_init(0, libxfs_ihash_size,
&libxfs_icache_operations);
- libxfs_bcache = cache_init(libxfs_bhash_size,
+ libxfs_bcache = cache_init(0, libxfs_bhash_size,
&libxfs_bcache_operations);
}
--
1.8.3.2
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 29/32] libxfs: work around do_div() not handling 32 bit numerators
[not found] <1380510944-8571-1-git-send-email-david@fromorbit.com>
` (27 preceding siblings ...)
2013-09-30 3:15 ` [PATCH 28/32] xfs_db: avoid libxfs buffer lookup warnings Dave Chinner
@ 2013-09-30 3:15 ` Dave Chinner
2013-09-30 3:15 ` [PATCH 30/32] db: enable metadump on CRC filesystems Dave Chinner
` (2 subsequent siblings)
31 siblings, 0 replies; 56+ messages in thread
From: Dave Chinner @ 2013-09-30 3:15 UTC (permalink / raw)
To: xfs
From: Dave Chinner <dchinner@redhat.com>
The libxfs dquot buffer code uses do_div() with a 32 bit numerator.
This gives incorrect results as do_div() passes the numerator by
reference as a pointer to a 64 bit value. Hence it does the division
using 32 bits of garbage gives the wrong result. The kernel code
handles 32 bit numerators just fine, so this patch is a temporary
workaround in the dquot buffer code until we fix do_div() to handle
32 bit numerators correctly.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
libxfs/xfs_dquot_buf.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/libxfs/xfs_dquot_buf.c b/libxfs/xfs_dquot_buf.c
index 620d9d3..ce6b09c 100644
--- a/libxfs/xfs_dquot_buf.c
+++ b/libxfs/xfs_dquot_buf.c
@@ -18,18 +18,28 @@
*/
#include "xfs.h"
+/*
+ * XXX: the userspace implementation of the do_div() macro does not handle 32
+ * bit numerators properly as it passes it by reference as a pointer to a 64 bit
+ * variable and dereferences it as such. Hence the result is way, way off
+ * because it uses 32 bits of garbage for the upper 32 bits of the numerator.
+ *
+ * This is being left here as a reminder that we need to fix do_div() in
+ * userspace as every time we do a libxfs kernel/userspace diff we'll see this
+ * comment.
+ */
int
xfs_calc_dquots_per_chunk(
struct xfs_mount *mp,
unsigned int nbblks) /* basic block units */
{
- unsigned int ndquots;
+ uint64_t ndquots;
ASSERT(nbblks > 0);
ndquots = BBTOB(nbblks);
do_div(ndquots, sizeof(xfs_dqblk_t));
- return ndquots;
+ return (int)ndquots;
}
/*
--
1.8.3.2
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 30/32] db: enable metadump on CRC filesystems
[not found] <1380510944-8571-1-git-send-email-david@fromorbit.com>
` (28 preceding siblings ...)
2013-09-30 3:15 ` [PATCH 29/32] libxfs: work around do_div() not handling 32 bit numerators Dave Chinner
@ 2013-09-30 3:15 ` Dave Chinner
2013-09-30 3:15 ` [PATCH 31/32] xfs: support larger inode clusters on v5 filesystems Dave Chinner
2013-09-30 3:15 ` [PATCH 32/32] xfsprogs: kill experimental warnings for " Dave Chinner
31 siblings, 0 replies; 56+ messages in thread
From: Dave Chinner @ 2013-09-30 3:15 UTC (permalink / raw)
To: xfs
From: Dave Chinner <dchinner@redhat.com>
Now that we can calculate CRCs through xfs_db, we can add support
for recalculating CRCs on obfuscated metadump images. This simply
requires us to call the write verifier manually before writing the
buffer to the metadump image.
We don't need to do anything special to mdrestore, as the metadata
blocks it reads from the image file should already have all the
correct CRCs in them. hence it can be mostly oblivious to the fact
that the filesystem it is resotring contains CRCs.
While there, add IO stack unwinding to xfs_db to prevent metadump
and other db programs from exiting with unreleased buffers in the IO
stack and hence emitting warnings like:
cache_purge: shake on cache 0x69e4f0 left 7 nodes!?
Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
db/init.c | 5 ++++-
db/metadump.c | 24 +++++++++++++++++++-----
mdrestore/xfs_mdrestore.c | 3 ---
3 files changed, 23 insertions(+), 9 deletions(-)
diff --git a/db/init.c b/db/init.c
index 2b643f9..dc915fb 100644
--- a/db/init.c
+++ b/db/init.c
@@ -173,9 +173,11 @@ main(
int c, i, done = 0;
char *input;
char **v;
+ int start_iocur_sp;
pushfile(stdin);
init(argc, argv);
+ start_iocur_sp = iocur_sp;
for (i = 0; !done && i < ncmdline; i++) {
v = breakline(cmdline[i], &c);
@@ -202,7 +204,8 @@ close_devices:
* make sure that we pop the last buffer context we held so that the
* buffer is released before purge the caches during unmount.
*/
- pop_cur();
+ while (iocur_sp > start_iocur_sp)
+ pop_cur();
libxfs_umount(mp);
if (x.ddev)
libxfs_device_close(x.ddev);
diff --git a/db/metadump.c b/db/metadump.c
index ac6a4d6..117dc42 100644
--- a/db/metadump.c
+++ b/db/metadump.c
@@ -172,6 +172,22 @@ write_buf(
__int64_t off;
int i;
+ /*
+ * Run the write verifier to recalculate the buffer CRCs and check
+ * we are writing something valid to disk
+ */
+ if (buf->bp && buf->bp->b_ops) {
+ buf->bp->b_error = 0;
+ buf->bp->b_ops->verify_write(buf->bp);
+ if (buf->bp->b_error) {
+ fprintf(stderr,
+ _("%s: write verifer failed on bno 0x%llx/0x%x\n"),
+ __func__, (long long)buf->bp->b_bn,
+ buf->bp->b_bcount);
+ return buf->bp->b_error;
+ }
+ }
+
for (i = 0, off = buf->bb, data = buf->data;
i < buf->blen;
i++, off++, data += BBSIZE) {
@@ -1727,6 +1743,9 @@ copy_inode_chunk(
if (!process_inode(agno, agino + i, dip))
goto pop_out;
+
+ /* calculate the new CRC for the inode */
+ xfs_dinode_calc_crc(mp, dip);
}
skip_processing:
if (!write_buf(iocur_top))
@@ -2053,11 +2072,6 @@ metadump_f(
return 0;
}
- if (xfs_sb_version_hascrc(&mp->m_sb) && dont_obfuscate == 0) {
- print_warning("Can't obfuscate CRC enabled filesystems yet.");
- return 0;
- }
-
metablock = (xfs_metablock_t *)calloc(BBSIZE + 1, BBSIZE);
if (metablock == NULL) {
print_warning("memory allocation failure");
diff --git a/mdrestore/xfs_mdrestore.c b/mdrestore/xfs_mdrestore.c
index fe61766..e57bdb2 100644
--- a/mdrestore/xfs_mdrestore.c
+++ b/mdrestore/xfs_mdrestore.c
@@ -109,9 +109,6 @@ perform_restore(
if (sb.sb_magicnum != XFS_SB_MAGIC)
fatal("bad magic number for primary superblock\n");
- if (xfs_sb_version_hascrc(&sb))
- fatal("Can't restore CRC enabled filesystems yet.\n");
-
((xfs_dsb_t*)block_buffer)->sb_inprogress = 1;
if (is_target_file) {
--
1.8.3.2
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 31/32] xfs: support larger inode clusters on v5 filesystems
[not found] <1380510944-8571-1-git-send-email-david@fromorbit.com>
` (29 preceding siblings ...)
2013-09-30 3:15 ` [PATCH 30/32] db: enable metadump on CRC filesystems Dave Chinner
@ 2013-09-30 3:15 ` Dave Chinner
2013-09-30 3:15 ` [PATCH 32/32] xfsprogs: kill experimental warnings for " Dave Chinner
31 siblings, 0 replies; 56+ messages in thread
From: Dave Chinner @ 2013-09-30 3:15 UTC (permalink / raw)
To: xfs
From: Dave Chinner <dchinner@redhat.com>
To allow the kernel to use larger inode clusters than the standard
8192 bytes, we need to set the inode alignment fields appropriately
so that the kernel is consistent in it's inode to buffer mappings.
We set the alignment to allow a constant 32 inodes per cluster,
instead of a fixed 8k cluster size.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
include/libxfs.h | 2 +-
mkfs/xfs_mkfs.c | 5 ++++-
repair/sb.c | 41 ++++++++++++++++++++++++++++-------------
3 files changed, 33 insertions(+), 15 deletions(-)
diff --git a/include/libxfs.h b/include/libxfs.h
index 049b217..9d7c579 100644
--- a/include/libxfs.h
+++ b/include/libxfs.h
@@ -182,7 +182,7 @@ typedef struct xfs_mount {
__uint8_t m_sectbb_log; /* sectorlog - BBSHIFT */
__uint8_t m_agno_log; /* log #ag's */
__uint8_t m_agino_log; /* #bits for agino in inum */
- __uint16_t m_inode_cluster_size;/* min inode buf size */
+ uint m_inode_cluster_size;/* min inode buf size */
uint m_blockmask; /* sb_blocksize-1 */
uint m_blockwsize; /* sb_blocksize in words */
uint m_blockwmask; /* blockwsize-1 */
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 60e4d88..feb5bd0 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -2501,7 +2501,10 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
} else
sbp->sb_logsunit = 0;
if (iaflag) {
- sbp->sb_inoalignmt = XFS_INODE_BIG_CLUSTER_SIZE >> blocklog;
+ int cluster_size = XFS_INODE_BIG_CLUSTER_SIZE;
+ if (crcs_enabled)
+ cluster_size *= isize / XFS_DINODE_MIN_SIZE;
+ sbp->sb_inoalignmt = cluster_size >> blocklog;
iaflag = sbp->sb_inoalignmt != 0;
} else
sbp->sb_inoalignmt = 0;
diff --git a/repair/sb.c b/repair/sb.c
index e2f5933..86404ce 100644
--- a/repair/sb.c
+++ b/repair/sb.c
@@ -169,17 +169,37 @@ find_secondary_sb(xfs_sb_t *rsb)
}
/*
- * calculate what inode alignment field ought to be
- * based on internal superblock info
+ * Calculate what inode alignment field ought to be
+ * based on internal superblock info and determine if it is valid.
+ *
+ * For v5 superblocks, the inode alignment will either match that of the
+ * standard XFS_INODE_BIG_CLUSTER_SIZE, or it will be scaled based on the inode
+ * size. Either value is valid in this case.
+ *
+ * Return true if the alignment is valid, false otherwise.
*/
-static int
-calc_ino_align(xfs_sb_t *sb)
+static bool
+sb_validate_ino_align(struct xfs_sb *sb)
{
- xfs_extlen_t align;
+ xfs_extlen_t align;
+ if (!xfs_sb_version_hasalign(sb))
+ return true;
+
+ /* standard cluster size alignment is always valid */
align = XFS_INODE_BIG_CLUSTER_SIZE >> sb->sb_blocklog;
+ if (align == sb->sb_inoalignmt)
+ return true;
+
+ /* alignment scaled by inode size is v5 only for now */
+ if (!xfs_sb_version_hascrc(sb))
+ return false;
- return(align);
+ align *= sb->sb_inodesize / XFS_DINODE_MIN_SIZE;
+ if (align == sb->sb_inoalignmt)
+ return true;
+
+ return false;
}
/*
@@ -228,7 +248,6 @@ int
verify_sb(xfs_sb_t *sb, int is_primary_sb)
{
__uint32_t bsize;
- xfs_extlen_t align;
int i;
/* check magic number and version number */
@@ -364,12 +383,8 @@ verify_sb(xfs_sb_t *sb, int is_primary_sb)
/*
* verify correctness of inode alignment if it's there
*/
- if (xfs_sb_version_hasalign(sb)) {
- align = calc_ino_align(sb);
-
- if (align != sb->sb_inoalignmt)
- return(XR_BAD_INO_ALIGN);
- }
+ if (!sb_validate_ino_align(sb))
+ return(XR_BAD_INO_ALIGN);
/*
* verify max. % of inodes (sb_imax_pct)
--
1.8.3.2
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 32/32] xfsprogs: kill experimental warnings for v5 filesystems
[not found] <1380510944-8571-1-git-send-email-david@fromorbit.com>
` (30 preceding siblings ...)
2013-09-30 3:15 ` [PATCH 31/32] xfs: support larger inode clusters on v5 filesystems Dave Chinner
@ 2013-09-30 3:15 ` Dave Chinner
31 siblings, 0 replies; 56+ messages in thread
From: Dave Chinner @ 2013-09-30 3:15 UTC (permalink / raw)
To: xfs
From: Dave Chinner <dchinner@redhat.com>
With xfsprogs now being close to feature complete on v5 filesystems,
remove the experimental warnings from the superblock verifier. This
means that we don't need to filter such warnings from the output in
xfstests and so we can see exactly what tests are failing due to
code deficiencies rather than from detecting warning noise.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
libxfs/xfs_sb.c | 4 ----
1 file changed, 4 deletions(-)
diff --git a/libxfs/xfs_sb.c b/libxfs/xfs_sb.c
index 8b90b88..6febcb3 100644
--- a/libxfs/xfs_sb.c
+++ b/libxfs/xfs_sb.c
@@ -180,10 +180,6 @@ xfs_mount_validate_sb(
* write validation, we don't need to check feature masks.
*/
if (check_version && XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) {
- xfs_alert(mp,
-"Version 5 superblock detected. xfsprogs has EXPERIMENTAL support enabled!\n"
-"Use of these features is at your own risk!");
-
if (xfs_sb_has_compat_feature(sbp,
XFS_SB_FEAT_COMPAT_UNKNOWN)) {
xfs_warn(mp,
--
1.8.3.2
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 56+ messages in thread
* Re: [PATCH 02/32] libxfs: fix missing filetype updates to xfs_dir2.c
2013-09-30 3:15 ` [PATCH 02/32] libxfs: fix missing filetype updates to xfs_dir2.c Dave Chinner
@ 2013-10-08 22:53 ` Eric Sandeen
2013-10-09 20:41 ` Dave Chinner
2013-10-18 16:45 ` Rich Johnston
1 sibling, 1 reply; 56+ messages in thread
From: Eric Sandeen @ 2013-10-08 22:53 UTC (permalink / raw)
To: Dave Chinner; +Cc: xfs
On 9/29/13 10:15 PM, Dave Chinner wrote:
> From: Dave Chinner <dchinner@redhat.com>
>
> They were missed in the original patch that was committed.
I'm not sure it's required in lookup or remove, at least today
nothing looks at it on those paths, does it?
Anyway, matches kernel, at worst the last 2 are harmless:
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
> ---
> libxfs/xfs_dir2.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/libxfs/xfs_dir2.c b/libxfs/xfs_dir2.c
> index 010c701..96a3c1d 100644
> --- a/libxfs/xfs_dir2.c
> +++ b/libxfs/xfs_dir2.c
> @@ -194,6 +194,7 @@ xfs_dir_createname(
> memset(&args, 0, sizeof(xfs_da_args_t));
> args.name = name->name;
> args.namelen = name->len;
> + args.filetype = name->type;
> args.hashval = dp->i_mount->m_dirnameops->hashname(name);
> args.inumber = inum;
> args.dp = dp;
> @@ -268,6 +269,7 @@ xfs_dir_lookup(
> memset(&args, 0, sizeof(xfs_da_args_t));
> args.name = name->name;
> args.namelen = name->len;
> + args.filetype = name->type;
> args.hashval = dp->i_mount->m_dirnameops->hashname(name);
> args.dp = dp;
> args.whichfork = XFS_DATA_FORK;
> @@ -323,6 +325,7 @@ xfs_dir_removename(
> memset(&args, 0, sizeof(xfs_da_args_t));
> args.name = name->name;
> args.namelen = name->len;
> + args.filetype = name->type;
> args.hashval = dp->i_mount->m_dirnameops->hashname(name);
> args.inumber = ino;
> args.dp = dp;
>
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [PATCH 03/32] xfs: fix some minor sparse warnings
2013-09-30 3:15 ` [PATCH 03/32] xfs: fix some minor sparse warnings Dave Chinner
@ 2013-10-08 22:56 ` Eric Sandeen
2013-10-09 20:43 ` Dave Chinner
0 siblings, 1 reply; 56+ messages in thread
From: Eric Sandeen @ 2013-10-08 22:56 UTC (permalink / raw)
To: Dave Chinner; +Cc: xfs
On 9/29/13 10:15 PM, Dave Chinner wrote:
> From: Dave Chinner <dchinner@redhat.com>
>
> A couple of simple locking annotations and 0 vs NULL warnings.
> Nothing that changes any code behaviour, just removes build noise.
The patch is fine as it is, but it doesn't reflect the commit log.
Is part of it missing?
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
> ---
> libxfs/xfs_bmap.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c
> index 2d480cc..7336abf 100644
> --- a/libxfs/xfs_bmap.c
> +++ b/libxfs/xfs_bmap.c
> @@ -4415,7 +4415,7 @@ xfs_bmapi_write(
> {
> struct xfs_mount *mp = ip->i_mount;
> struct xfs_ifork *ifp;
> - struct xfs_bmalloca bma = { 0 }; /* args for xfs_bmap_alloc */
> + struct xfs_bmalloca bma = { NULL }; /* args for xfs_bmap_alloc */
> xfs_fileoff_t end; /* end of mapped file region */
> int eof; /* after the end of extents */
> int error; /* error return */
>
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [PATCH 01/32] xfsprogs: fix automatic dependency generation
2013-09-30 3:15 ` [PATCH 01/32] xfsprogs: fix automatic dependency generation Dave Chinner
@ 2013-10-08 23:00 ` Eric Sandeen
0 siblings, 0 replies; 56+ messages in thread
From: Eric Sandeen @ 2013-10-08 23:00 UTC (permalink / raw)
To: Dave Chinner; +Cc: xfs
On 9/29/13 10:15 PM, Dave Chinner wrote:
> From: Dave Chinner <dchinner@redhat.com>
>
> Adding are removing a header file does not result in dependency
s/are/or/
> regeneration like it should. make clean will rebuild the
> dependencies, but a normal make won't. Fix it.
>
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
> ---
> include/buildrules | 20 ++++++++++++++++----
> 1 file changed, 16 insertions(+), 4 deletions(-)
>
> diff --git a/include/buildrules b/include/buildrules
> index 49cb2a4..edb1beb 100644
> --- a/include/buildrules
> +++ b/include/buildrules
> @@ -79,18 +79,30 @@ endif # _BUILDRULES_INCLUDED_
> $(_FORCE):
>
> # dependency build is automatic, relies on gcc -MM to generate.
> +#
> +# This is a bit messy. It regenerates the depenencies on each build so
dependencies
I'm no make guru but seems relatively harmless. ;)
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
> +# that we catch files being added and removed. There are other ways of doing
> +# this (e.g. per-file dependency files) but that requires more in-depth changes
> +# to the build system. Compile time is not an issue for us, so the
> +# rebuild on every make invocation isn't a problem we need to care about. Just
> +# do it silently so it doesn't make the build unnecessarily noisy.
> +
> .PHONY : depend ltdepend install-qa
>
> MAKEDEP := $(MAKEDEPEND) $(CFLAGS)
>
> -ltdepend: .ltdep
> +ltdepend: rmltdep .ltdep
> +
> +rmltdep:
> + @rm -f .ltdep
>
> .ltdep: $(CFILES) $(HFILES)
> - @echo " [LTDEP]"
> $(Q)$(MAKEDEP) $(CFILES) | $(SED) -e 's,^\([^:]*\)\.o,\1.lo,' > .ltdep
>
> -depend: .dep
> +depend: rmdep .dep
> +
> +rmdep:
> + @rm -f .dep
>
> .dep: $(CFILES) $(HFILES)
> - @echo " [DEP]"
> $(Q)$(MAKEDEP) $(CFILES) > .dep
>
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [PATCH 04/32] xfs: check magic numbers in dir3 leaf verifier first
2013-09-30 3:15 ` [PATCH 04/32] xfs: check magic numbers in dir3 leaf verifier first Dave Chinner
@ 2013-10-08 23:03 ` Eric Sandeen
2013-10-09 20:45 ` Dave Chinner
0 siblings, 1 reply; 56+ messages in thread
From: Eric Sandeen @ 2013-10-08 23:03 UTC (permalink / raw)
To: Dave Chinner; +Cc: xfs
On 9/29/13 10:15 PM, Dave Chinner wrote:
> From: Dave Chinner <dchinner@redhat.com>
>
> Calling xfs_dir3_leaf_hdr_from_disk() in a verifier before
> validating the magic numbers in the buffer results in ASSERT
> failures due to mismatching magic numbers when a corruption occurs.
> Seeing as the verifier is supposed to catch the corruption and pass
> it back to the caller, having the verifier assert fail on error
> defeats the purpose of detecting the errors in the first place.
>
> Check the magic numbers direct from the buffer before decoding the
> header.
Looks good; have you sent this for the kernel yet?
(I thought we wanted changes to hit kernelspace first) :)
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
> ---
> libxfs/xfs_dir2_leaf.c | 20 +++++++++++++-------
> 1 file changed, 13 insertions(+), 7 deletions(-)
>
> diff --git a/libxfs/xfs_dir2_leaf.c b/libxfs/xfs_dir2_leaf.c
> index 7ec2f19..c035c4d 100644
> --- a/libxfs/xfs_dir2_leaf.c
> +++ b/libxfs/xfs_dir2_leaf.c
> @@ -161,6 +161,11 @@ xfs_dir3_leaf_check_int(
> return true;
> }
>
> +/*
> + * We verify the magic numbers before decoding the leaf header so that on debug
> + * kernels we don't get assertion failures in xfs_dir3_leaf_hdr_from_disk() due
> + * to incorrect magic numbers.
> + */
> static bool
> xfs_dir3_leaf_verify(
> struct xfs_buf *bp,
> @@ -172,24 +177,25 @@ xfs_dir3_leaf_verify(
>
> ASSERT(magic == XFS_DIR2_LEAF1_MAGIC || magic == XFS_DIR2_LEAFN_MAGIC);
>
> - xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf);
> if (xfs_sb_version_hascrc(&mp->m_sb)) {
> struct xfs_dir3_leaf_hdr *leaf3 = bp->b_addr;
> + __uint16_t magic3;
>
> - if ((magic == XFS_DIR2_LEAF1_MAGIC &&
> - leafhdr.magic != XFS_DIR3_LEAF1_MAGIC) ||
> - (magic == XFS_DIR2_LEAFN_MAGIC &&
> - leafhdr.magic != XFS_DIR3_LEAFN_MAGIC))
> - return false;
> + magic3 = (magic == XFS_DIR2_LEAF1_MAGIC) ? XFS_DIR3_LEAF1_MAGIC
> + : XFS_DIR3_LEAFN_MAGIC;
>
> + if (leaf3->info.hdr.magic != cpu_to_be16(magic3))
> + return false;
> if (!uuid_equal(&leaf3->info.uuid, &mp->m_sb.sb_uuid))
> return false;
> if (be64_to_cpu(leaf3->info.blkno) != bp->b_bn)
> return false;
> } else {
> - if (leafhdr.magic != magic)
> + if (leaf->hdr.info.magic != cpu_to_be16(magic))
> return false;
> }
> +
> + xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf);
> return xfs_dir3_leaf_check_int(mp, &leafhdr, leaf);
> }
>
>
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [PATCH 05/32] xfs: ensure we copy buffer type in da btree root splits
2013-09-30 3:15 ` [PATCH 05/32] xfs: ensure we copy buffer type in da btree root splits Dave Chinner
@ 2013-10-08 23:06 ` Eric Sandeen
2013-10-18 16:49 ` Rich Johnston
1 sibling, 0 replies; 56+ messages in thread
From: Eric Sandeen @ 2013-10-08 23:06 UTC (permalink / raw)
To: Dave Chinner; +Cc: xfs
On 9/29/13 10:15 PM, Dave Chinner wrote:
> From: Dave Chinner <dchinner@redhat.com>
>
> When splitting the root of the da btree, we shuffled data between
> buffers and the structures that track them. At one point, we copy
> data and state from one buffer to another, including the ops
> associated with the buffer. When we do this, we also need to copy
> the buffer type associated with the buf log item so that the buffer
> is logged correctly. If we don't do that, log recovery won't
> recognise it and hence it won't recalculate the CRC on the buffer
> after recovery. This leads to a directory block that can't be read
> after recovery has run.
>
> Found by inspection after finding the same problem with remote
> symlink buffers.
Makes sense, matches kernel commit 0a4edc8f0b54cd5f613e7fda7dc8106cb9869bc9
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
> ---
> libxfs/xfs_da_btree.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/libxfs/xfs_da_btree.c b/libxfs/xfs_da_btree.c
> index b7b6705..f106e06 100644
> --- a/libxfs/xfs_da_btree.c
> +++ b/libxfs/xfs_da_btree.c
> @@ -612,6 +612,7 @@ xfs_da3_root_split(
> xfs_trans_log_buf(tp, bp, 0, size - 1);
>
> bp->b_ops = blk1->bp->b_ops;
> + xfs_trans_buf_copy_type(bp, blk1->bp);
> blk1->bp = bp;
> blk1->blkno = blkno;
>
>
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [PATCH 06/32] xfs: don't assert fail on bad inode numbers
2013-09-30 3:15 ` [PATCH 06/32] xfs: don't assert fail on bad inode numbers Dave Chinner
@ 2013-10-08 23:09 ` Eric Sandeen
0 siblings, 0 replies; 56+ messages in thread
From: Eric Sandeen @ 2013-10-08 23:09 UTC (permalink / raw)
To: Dave Chinner; +Cc: xfs
On 9/29/13 10:15 PM, Dave Chinner wrote:
> From: Dave Chinner <dchinner@redhat.com>
>
> Let the inode verifier do it's work by returning an error when we
> fail to find correct magic numbers in an inode buffer.
Makes sense & matches kernel 74ffa796e127906883cacedcf3871494192c9e42
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
> ---
> libxfs/xfs_inode_buf.c | 8 +++-----
> 1 file changed, 3 insertions(+), 5 deletions(-)
>
> diff --git a/libxfs/xfs_inode_buf.c b/libxfs/xfs_inode_buf.c
> index 6205318..b096f77 100644
> --- a/libxfs/xfs_inode_buf.c
> +++ b/libxfs/xfs_inode_buf.c
> @@ -39,9 +39,8 @@ xfs_inobp_check(
> i * mp->m_sb.sb_inodesize);
> if (!dip->di_next_unlinked) {
> xfs_alert(mp,
> - "Detected bogus zero next_unlinked field in incore inode buffer 0x%p.",
> - bp);
> - ASSERT(dip->di_next_unlinked);
> + "Detected bogus zero next_unlinked field in inode %d buffer 0x%llx.",
> + i, (long long)bp->b_bn);
> }
> }
> }
> @@ -74,11 +73,10 @@ xfs_inode_buf_verify(
> XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_HIGH,
> mp, dip);
> #ifdef DEBUG
> - xfs_emerg(mp,
> + xfs_alert(mp,
> "bad inode magic/vsn daddr %lld #%d (magic=%x)",
> (unsigned long long)bp->b_bn, i,
> be16_to_cpu(dip->di_magic));
> - ASSERT(0);
> #endif
> }
> }
>
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [PATCH 07/32] xfs: dirent dtype presence is dependent on directory magic numbers
2013-09-30 3:15 ` [PATCH 07/32] xfs: dirent dtype presence is dependent on directory magic numbers Dave Chinner
@ 2013-10-08 23:30 ` Eric Sandeen
2013-10-09 20:51 ` Dave Chinner
2013-10-18 22:38 ` Rich Johnston
0 siblings, 2 replies; 56+ messages in thread
From: Eric Sandeen @ 2013-10-08 23:30 UTC (permalink / raw)
To: Dave Chinner; +Cc: xfs
On 9/29/13 10:15 PM, Dave Chinner wrote:
> From: Dave Chinner <dchinner@redhat.com>
>
> The determination of whether a directory entry contains a dtype
> field originally was dependent on the filesystem having CRCs
> enabled. This meant that the format for dtype beign enabled could be
> determined by checking the directory block magic number rather than
> doing a feature bit check. This was useful in that it meant that we
> didn't need to pass a struct xfs_mount around to functions that
> were already supplied with a directory block header.
>
> Unfortunately, the introduction of dtype fields into the v4
> structure via a feature bit meant this "use the directory block
> magic number" method of discriminating the dirent entry sizes is
> broken. Hence we need to convert the places that use magic number
> checks to use feature bit checks so that they work correctly and not
> by chance.
>
> The current code works on v4 filesystems only because the dirent
> size roundup covers the extra byte needed by the dtype field in the
> places where this problem occurs.
Looks right to me. Nitpicks & questions though:
FWIW, I find it confusing that we call xfs_dir3_*()
functions from dir2 code or to find out whether the
dir is in fact dir2 or dir3.
i.e.:
return xfs_dir3_data_hdr_size(xfs_sb_version_hascrc(&mp->m_sb));
that just seems like an odd name to calculate the header size for
dir2 vs. dir3 directories.
Also -
Is there any pro or con to defining the 3 offsets recursively:
static inline xfs_dir2_data_aoff_t
xfs_dir3_data_dot_offset(struct xfs_mount *mp)
{
return xfs_dir3_data_hdr_size(xfs_sb_version_hascrc(&mp->m_sb));
}
static inline xfs_dir2_data_aoff_t
xfs_dir3_data_dotdot_offset(struct xfs_mount *mp)
{
return xfs_dir3_data_dot_offset(mp) +
xfs_dir3_data_entsize(mp, 1);
}
static inline xfs_dir2_data_aoff_t
xfs_dir3_data_first_offset(struct xfs_mount *mp)
{
return xfs_dir3_data_dotdot_offset(mp) +
xfs_dir3_data_entsize(mp, 2);
}
vs directly, i.e.:
static inline xfs_dir2_data_aoff_t
xfs_dir3_data_first_offset(struct xfs_mount *mp)
{
return xfs_dir3_data_hdr_size(xfs_sb_version_hascrc(&mp->m_sb)) +
xfs_dir3_data_entsize(mp, 1); /* Dot */
xfs_dir3_data_entsize(mp, 2); /* Dotdot */
}
?
Looks technically correct though, so:
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
-Eric
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
> ---
> db/check.c | 2 +-
> include/xfs_dir2_format.h | 51 +++++++++++++++++++----------------------------
> libxfs/xfs_dir2_block.c | 6 +++---
> libxfs/xfs_dir2_sf.c | 6 +++---
> repair/dir2.c | 4 ++--
> 5 files changed, 29 insertions(+), 40 deletions(-)
>
> diff --git a/db/check.c b/db/check.c
> index 2d4718d..4867698 100644
> --- a/db/check.c
> +++ b/db/check.c
> @@ -3434,7 +3434,7 @@ process_sf_dir_v2(
> dbprintf(_("dir %lld entry . %lld\n"), id->ino, id->ino);
> (*dot)++;
> sfe = xfs_dir2_sf_firstentry(sf);
> - offset = XFS_DIR3_DATA_FIRST_OFFSET(mp);
> + offset = xfs_dir3_data_first_offset(mp);
> for (i = sf->count - 1, i8 = 0; i >= 0; i--) {
> if ((__psint_t)sfe + xfs_dir3_sf_entsize(mp, sf, sfe->namelen) -
> (__psint_t)sf > be64_to_cpu(dip->di_size)) {
> diff --git a/include/xfs_dir2_format.h b/include/xfs_dir2_format.h
> index a0961a6..9cf6738 100644
> --- a/include/xfs_dir2_format.h
> +++ b/include/xfs_dir2_format.h
> @@ -497,69 +497,58 @@ xfs_dir3_data_unused_p(struct xfs_dir2_data_hdr *hdr)
> /*
> * Offsets of . and .. in data space (always block 0)
> *
> - * The macros are used for shortform directories as they have no headers to read
> - * the magic number out of. Shortform directories need to know the size of the
> - * data block header because the sfe embeds the block offset of the entry into
> - * it so that it doesn't change when format conversion occurs. Bad Things Happen
> - * if we don't follow this rule.
> - *
> * XXX: there is scope for significant optimisation of the logic here. Right
> * now we are checking for "dir3 format" over and over again. Ideally we should
> * only do it once for each operation.
> */
> -#define XFS_DIR3_DATA_DOT_OFFSET(mp) \
> - xfs_dir3_data_hdr_size(xfs_sb_version_hascrc(&(mp)->m_sb))
> -#define XFS_DIR3_DATA_DOTDOT_OFFSET(mp) \
> - (XFS_DIR3_DATA_DOT_OFFSET(mp) + xfs_dir3_data_entsize(mp, 1))
> -#define XFS_DIR3_DATA_FIRST_OFFSET(mp) \
> - (XFS_DIR3_DATA_DOTDOT_OFFSET(mp) + xfs_dir3_data_entsize(mp, 2))
> -
> static inline xfs_dir2_data_aoff_t
> -xfs_dir3_data_dot_offset(struct xfs_dir2_data_hdr *hdr)
> +xfs_dir3_data_dot_offset(struct xfs_mount *mp)
> {
> - return xfs_dir3_data_entry_offset(hdr);
> + return xfs_dir3_data_hdr_size(xfs_sb_version_hascrc(&mp->m_sb));
> }
>
> static inline xfs_dir2_data_aoff_t
> -xfs_dir3_data_dotdot_offset(struct xfs_dir2_data_hdr *hdr)
> +xfs_dir3_data_dotdot_offset(struct xfs_mount *mp)
> {
> - bool dir3 = hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
> - hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC);
> - return xfs_dir3_data_dot_offset(hdr) +
> - __xfs_dir3_data_entsize(dir3, 1);
> + return xfs_dir3_data_dot_offset(mp) +
> + xfs_dir3_data_entsize(mp, 1);
> }
>
> static inline xfs_dir2_data_aoff_t
> -xfs_dir3_data_first_offset(struct xfs_dir2_data_hdr *hdr)
> +xfs_dir3_data_first_offset(struct xfs_mount *mp)
> {
> - bool dir3 = hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
> - hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC);
> - return xfs_dir3_data_dotdot_offset(hdr) +
> - __xfs_dir3_data_entsize(dir3, 2);
> + return xfs_dir3_data_dotdot_offset(mp) +
> + xfs_dir3_data_entsize(mp, 2);
> }
>
> /*
> * location of . and .. in data space (always block 0)
> */
> static inline struct xfs_dir2_data_entry *
> -xfs_dir3_data_dot_entry_p(struct xfs_dir2_data_hdr *hdr)
> +xfs_dir3_data_dot_entry_p(
> + struct xfs_mount *mp,
> + struct xfs_dir2_data_hdr *hdr)
> {
> return (struct xfs_dir2_data_entry *)
> - ((char *)hdr + xfs_dir3_data_dot_offset(hdr));
> + ((char *)hdr + xfs_dir3_data_dot_offset(mp));
> }
>
> static inline struct xfs_dir2_data_entry *
> -xfs_dir3_data_dotdot_entry_p(struct xfs_dir2_data_hdr *hdr)
> +xfs_dir3_data_dotdot_entry_p(
> + struct xfs_mount *mp,
> + struct xfs_dir2_data_hdr *hdr)
> {
> return (struct xfs_dir2_data_entry *)
> - ((char *)hdr + xfs_dir3_data_dotdot_offset(hdr));
> + ((char *)hdr + xfs_dir3_data_dotdot_offset(mp));
> }
>
> static inline struct xfs_dir2_data_entry *
> -xfs_dir3_data_first_entry_p(struct xfs_dir2_data_hdr *hdr)
> +xfs_dir3_data_first_entry_p(
> + struct xfs_mount *mp,
> + struct xfs_dir2_data_hdr *hdr)
> {
> return (struct xfs_dir2_data_entry *)
> - ((char *)hdr + xfs_dir3_data_first_offset(hdr));
> + ((char *)hdr + xfs_dir3_data_first_offset(mp));
> }
>
> /*
> diff --git a/libxfs/xfs_dir2_block.c b/libxfs/xfs_dir2_block.c
> index 3e4bc53..1d8f598 100644
> --- a/libxfs/xfs_dir2_block.c
> +++ b/libxfs/xfs_dir2_block.c
> @@ -1139,7 +1139,7 @@ xfs_dir2_sf_to_block(
> /*
> * Create entry for .
> */
> - dep = xfs_dir3_data_dot_entry_p(hdr);
> + dep = xfs_dir3_data_dot_entry_p(mp, hdr);
> dep->inumber = cpu_to_be64(dp->i_ino);
> dep->namelen = 1;
> dep->name[0] = '.';
> @@ -1153,7 +1153,7 @@ xfs_dir2_sf_to_block(
> /*
> * Create entry for ..
> */
> - dep = xfs_dir3_data_dotdot_entry_p(hdr);
> + dep = xfs_dir3_data_dotdot_entry_p(mp, hdr);
> dep->inumber = cpu_to_be64(xfs_dir2_sf_get_parent_ino(sfp));
> dep->namelen = 2;
> dep->name[0] = dep->name[1] = '.';
> @@ -1164,7 +1164,7 @@ xfs_dir2_sf_to_block(
> blp[1].hashval = cpu_to_be32(xfs_dir_hash_dotdot);
> blp[1].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp,
> (char *)dep - (char *)hdr));
> - offset = xfs_dir3_data_first_offset(hdr);
> + offset = xfs_dir3_data_first_offset(mp);
> /*
> * Loop over existing entries, stuff them in.
> */
> diff --git a/libxfs/xfs_dir2_sf.c b/libxfs/xfs_dir2_sf.c
> index 740cab0..7580333 100644
> --- a/libxfs/xfs_dir2_sf.c
> +++ b/libxfs/xfs_dir2_sf.c
> @@ -540,7 +540,7 @@ xfs_dir2_sf_addname_hard(
> * to insert the new entry.
> * If it's going to end up at the end then oldsfep will point there.
> */
> - for (offset = XFS_DIR3_DATA_FIRST_OFFSET(mp),
> + for (offset = xfs_dir3_data_first_offset(mp),
> oldsfep = xfs_dir2_sf_firstentry(oldsfp),
> add_datasize = xfs_dir3_data_entsize(mp, args->namelen),
> eof = (char *)oldsfep == &buf[old_isize];
> @@ -623,7 +623,7 @@ xfs_dir2_sf_addname_pick(
>
> sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
> size = xfs_dir3_data_entsize(mp, args->namelen);
> - offset = XFS_DIR3_DATA_FIRST_OFFSET(mp);
> + offset = xfs_dir3_data_first_offset(mp);
> sfep = xfs_dir2_sf_firstentry(sfp);
> holefit = 0;
> /*
> @@ -696,7 +696,7 @@ xfs_dir2_sf_check(
> mp = dp->i_mount;
>
> sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
> - offset = XFS_DIR3_DATA_FIRST_OFFSET(mp);
> + offset = xfs_dir3_data_first_offset(mp);
> ino = xfs_dir2_sf_get_parent_ino(sfp);
> i8count = ino > XFS_DIR2_MAX_SHORT_INUM;
>
> diff --git a/repair/dir2.c b/repair/dir2.c
> index a856631..d931d1d 100644
> --- a/repair/dir2.c
> +++ b/repair/dir2.c
> @@ -705,7 +705,7 @@ process_sf_dir2_fixoff(
>
> sfp = (struct xfs_dir2_sf_hdr *)XFS_DFORK_DPTR(dip);
> sfep = xfs_dir2_sf_firstentry(sfp);
> - offset = XFS_DIR3_DATA_FIRST_OFFSET(mp);
> + offset = xfs_dir3_data_first_offset(mp);
>
> for (i = 0; i < sfp->count; i++) {
> xfs_dir2_sf_put_offset(sfep, offset);
> @@ -759,7 +759,7 @@ process_sf_dir2(
> max_size = XFS_DFORK_DSIZE(dip, mp);
> num_entries = sfp->count;
> ino_dir_size = be64_to_cpu(dip->di_size);
> - offset = XFS_DIR3_DATA_FIRST_OFFSET(mp);
> + offset = xfs_dir3_data_first_offset(mp);
> bad_offset = *repair = 0;
>
> ASSERT(ino_dir_size <= max_size);
>
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [PATCH 08/32] xfs: create a shared header file for format-related information
2013-09-30 3:15 ` [PATCH 08/32] xfs: create a shared header file for format-related information Dave Chinner
@ 2013-10-08 23:37 ` Eric Sandeen
2013-10-18 16:59 ` Rich Johnston
1 sibling, 0 replies; 56+ messages in thread
From: Eric Sandeen @ 2013-10-08 23:37 UTC (permalink / raw)
To: Dave Chinner; +Cc: xfs
On 9/29/13 10:15 PM, Dave Chinner wrote:
> All of the buffer operations structures are needed to be exported
> for xfs_db, so move them all to a common location rather than
> spreading them all over the place. They are verifying the on-disk
> format, so while xfs_format.h might be a good place, it is not part
> of the on disk format.
>
> Hence we need to create a new header file that we centralise these
> related definitions. Start by moving the bffer operations
> structures, and then also move all the other definitions that have
> crept into xfs_log_format.h and xfs_format.h as there was no other
> shared header file to put them in.
>
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
All lines present & accounted for in new file. ;)
Would be nice to fix:
"* This determine how hard the buffer cache tries to hold onto"
while you're at it, but *shrug*
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
> ---
> include/Makefile | 1 +
> include/libxfs.h | 1 +
> include/xfs_ag.h | 4 -
> include/xfs_alloc.h | 3 -
> include/xfs_alloc_btree.h | 2 -
> include/xfs_attr_leaf.h | 2 -
> include/xfs_attr_remote.h | 2 -
> include/xfs_bmap_btree.h | 2 -
> include/xfs_da_btree.h | 2 -
> include/xfs_format.h | 10 --
> include/xfs_ialloc.h | 2 -
> include/xfs_ialloc_btree.h | 2 -
> include/xfs_inode_buf.h | 2 -
> include/xfs_log_format.h | 177 --------------------------------
> include/xfs_sb.h | 3 -
> include/xfs_shared.h | 244 +++++++++++++++++++++++++++++++++++++++++++++
> 16 files changed, 246 insertions(+), 213 deletions(-)
> create mode 100644 include/xfs_shared.h
>
> diff --git a/include/Makefile b/include/Makefile
> index 628a087..fd2d61b 100644
> --- a/include/Makefile
> +++ b/include/Makefile
> @@ -38,6 +38,7 @@ QAHFILES = libxfs.h libxlog.h \
> xfs_metadump.h \
> xfs_quota_defs.h \
> xfs_sb.h \
> + xfs_shared.h \
> xfs_trace.h \
> xfs_trans_resv.h \
> xfs_trans_space.h
> diff --git a/include/libxfs.h b/include/libxfs.h
> index ffd83bf..a5d6388 100644
> --- a/include/libxfs.h
> +++ b/include/libxfs.h
> @@ -37,6 +37,7 @@
> #include <xfs/xfs_fs.h>
> #include <xfs/xfs_arch.h>
>
> +#include <xfs/xfs_shared.h>
> #include <xfs/xfs_format.h>
> #include <xfs/xfs_log_format.h>
> #include <xfs/xfs_quota_defs.h>
> diff --git a/include/xfs_ag.h b/include/xfs_ag.h
> index 1cb740a..3fc1098 100644
> --- a/include/xfs_ag.h
> +++ b/include/xfs_ag.h
> @@ -128,8 +128,6 @@ typedef struct xfs_agf {
> extern int xfs_read_agf(struct xfs_mount *mp, struct xfs_trans *tp,
> xfs_agnumber_t agno, int flags, struct xfs_buf **bpp);
>
> -extern const struct xfs_buf_ops xfs_agf_buf_ops;
> -
> /*
> * Size of the unlinked inode hash table in the agi.
> */
> @@ -191,8 +189,6 @@ typedef struct xfs_agi {
> extern int xfs_read_agi(struct xfs_mount *mp, struct xfs_trans *tp,
> xfs_agnumber_t agno, struct xfs_buf **bpp);
>
> -extern const struct xfs_buf_ops xfs_agi_buf_ops;
> -
> /*
> * The third a.g. block contains the a.g. freelist, an array
> * of block pointers to blocks owned by the allocation btree code.
> diff --git a/include/xfs_alloc.h b/include/xfs_alloc.h
> index 99d0a61..feacb06 100644
> --- a/include/xfs_alloc.h
> +++ b/include/xfs_alloc.h
> @@ -231,7 +231,4 @@ xfs_alloc_get_rec(
> xfs_extlen_t *len, /* output: length of extent */
> int *stat); /* output: success/failure */
>
> -extern const struct xfs_buf_ops xfs_agf_buf_ops;
> -extern const struct xfs_buf_ops xfs_agfl_buf_ops;
> -
> #endif /* __XFS_ALLOC_H__ */
> diff --git a/include/xfs_alloc_btree.h b/include/xfs_alloc_btree.h
> index e3a3f74..72676c3 100644
> --- a/include/xfs_alloc_btree.h
> +++ b/include/xfs_alloc_btree.h
> @@ -95,6 +95,4 @@ extern struct xfs_btree_cur *xfs_allocbt_init_cursor(struct xfs_mount *,
> xfs_agnumber_t, xfs_btnum_t);
> extern int xfs_allocbt_maxrecs(struct xfs_mount *, int, int);
>
> -extern const struct xfs_buf_ops xfs_allocbt_buf_ops;
> -
> #endif /* __XFS_ALLOC_BTREE_H__ */
> diff --git a/include/xfs_attr_leaf.h b/include/xfs_attr_leaf.h
> index c102213..da34e64 100644
> --- a/include/xfs_attr_leaf.h
> +++ b/include/xfs_attr_leaf.h
> @@ -336,6 +336,4 @@ void xfs_attr3_leaf_hdr_from_disk(struct xfs_attr3_icleaf_hdr *to,
> void xfs_attr3_leaf_hdr_to_disk(struct xfs_attr_leafblock *to,
> struct xfs_attr3_icleaf_hdr *from);
>
> -extern const struct xfs_buf_ops xfs_attr3_leaf_buf_ops;
> -
> #endif /* __XFS_ATTR_LEAF_H__ */
> diff --git a/include/xfs_attr_remote.h b/include/xfs_attr_remote.h
> index 92a8fd7..b3e1e1b 100644
> --- a/include/xfs_attr_remote.h
> +++ b/include/xfs_attr_remote.h
> @@ -45,8 +45,6 @@ struct xfs_attr3_rmt_hdr {
> ((bufsize) - (xfs_sb_version_hascrc(&(mp)->m_sb) ? \
> sizeof(struct xfs_attr3_rmt_hdr) : 0))
>
> -extern const struct xfs_buf_ops xfs_attr3_rmt_buf_ops;
> -
> int xfs_attr3_rmt_blocks(struct xfs_mount *mp, int attrlen);
>
> int xfs_attr_rmtval_get(struct xfs_da_args *args);
> diff --git a/include/xfs_bmap_btree.h b/include/xfs_bmap_btree.h
> index 1b726d6..e307978 100644
> --- a/include/xfs_bmap_btree.h
> +++ b/include/xfs_bmap_btree.h
> @@ -239,6 +239,4 @@ extern int xfs_bmbt_maxrecs(struct xfs_mount *, int blocklen, int leaf);
> extern struct xfs_btree_cur *xfs_bmbt_init_cursor(struct xfs_mount *,
> struct xfs_trans *, struct xfs_inode *, int);
>
> -extern const struct xfs_buf_ops xfs_bmbt_buf_ops;
> -
> #endif /* __XFS_BMAP_BTREE_H__ */
> diff --git a/include/xfs_da_btree.h b/include/xfs_da_btree.h
> index b1f2679..a762cfa 100644
> --- a/include/xfs_da_btree.h
> +++ b/include/xfs_da_btree.h
> @@ -309,8 +309,6 @@ int xfs_da3_node_read(struct xfs_trans *tp, struct xfs_inode *dp,
> xfs_dablk_t bno, xfs_daddr_t mappedbno,
> struct xfs_buf **bpp, int which_fork);
>
> -extern const struct xfs_buf_ops xfs_da3_node_buf_ops;
> -
> /*
> * Utility routines.
> */
> diff --git a/include/xfs_format.h b/include/xfs_format.h
> index 35c08ff..a790428 100644
> --- a/include/xfs_format.h
> +++ b/include/xfs_format.h
> @@ -156,14 +156,4 @@ struct xfs_dsymlink_hdr {
> ((bufsize) - (xfs_sb_version_hascrc(&(mp)->m_sb) ? \
> sizeof(struct xfs_dsymlink_hdr) : 0))
>
> -int xfs_symlink_blocks(struct xfs_mount *mp, int pathlen);
> -int xfs_symlink_hdr_set(struct xfs_mount *mp, xfs_ino_t ino, uint32_t offset,
> - uint32_t size, struct xfs_buf *bp);
> -bool xfs_symlink_hdr_ok(struct xfs_mount *mp, xfs_ino_t ino, uint32_t offset,
> - uint32_t size, struct xfs_buf *bp);
> -void xfs_symlink_local_to_remote(struct xfs_trans *tp, struct xfs_buf *bp,
> - struct xfs_inode *ip, struct xfs_ifork *ifp);
> -
> -extern const struct xfs_buf_ops xfs_symlink_buf_ops;
> -
> #endif /* __XFS_FORMAT_H__ */
> diff --git a/include/xfs_ialloc.h b/include/xfs_ialloc.h
> index 68c0732..1557798 100644
> --- a/include/xfs_ialloc.h
> +++ b/include/xfs_ialloc.h
> @@ -158,6 +158,4 @@ int xfs_ialloc_inode_init(struct xfs_mount *mp, struct xfs_trans *tp,
> xfs_agnumber_t agno, xfs_agblock_t agbno,
> xfs_agblock_t length, unsigned int gen);
>
> -extern const struct xfs_buf_ops xfs_agi_buf_ops;
> -
> #endif /* __XFS_IALLOC_H__ */
> diff --git a/include/xfs_ialloc_btree.h b/include/xfs_ialloc_btree.h
> index 3ac36b7..cfbfe46 100644
> --- a/include/xfs_ialloc_btree.h
> +++ b/include/xfs_ialloc_btree.h
> @@ -110,6 +110,4 @@ extern struct xfs_btree_cur *xfs_inobt_init_cursor(struct xfs_mount *,
> struct xfs_trans *, struct xfs_buf *, xfs_agnumber_t);
> extern int xfs_inobt_maxrecs(struct xfs_mount *, int, int);
>
> -extern const struct xfs_buf_ops xfs_inobt_buf_ops;
> -
> #endif /* __XFS_IALLOC_BTREE_H__ */
> diff --git a/include/xfs_inode_buf.h b/include/xfs_inode_buf.h
> index aae9fc4..e8fd3bd 100644
> --- a/include/xfs_inode_buf.h
> +++ b/include/xfs_inode_buf.h
> @@ -47,6 +47,4 @@ void xfs_inobp_check(struct xfs_mount *, struct xfs_buf *);
> #define xfs_inobp_check(mp, bp)
> #endif /* DEBUG */
>
> -extern const struct xfs_buf_ops xfs_inode_buf_ops;
> -
> #endif /* __XFS_INODE_BUF_H__ */
> diff --git a/include/xfs_log_format.h b/include/xfs_log_format.h
> index 31e3a06..aeaa715 100644
> --- a/include/xfs_log_format.h
> +++ b/include/xfs_log_format.h
> @@ -234,178 +234,6 @@ typedef struct xfs_trans_header {
> { XFS_LI_ICREATE, "XFS_LI_ICREATE" }
>
> /*
> - * Transaction types. Used to distinguish types of buffers.
> - */
> -#define XFS_TRANS_SETATTR_NOT_SIZE 1
> -#define XFS_TRANS_SETATTR_SIZE 2
> -#define XFS_TRANS_INACTIVE 3
> -#define XFS_TRANS_CREATE 4
> -#define XFS_TRANS_CREATE_TRUNC 5
> -#define XFS_TRANS_TRUNCATE_FILE 6
> -#define XFS_TRANS_REMOVE 7
> -#define XFS_TRANS_LINK 8
> -#define XFS_TRANS_RENAME 9
> -#define XFS_TRANS_MKDIR 10
> -#define XFS_TRANS_RMDIR 11
> -#define XFS_TRANS_SYMLINK 12
> -#define XFS_TRANS_SET_DMATTRS 13
> -#define XFS_TRANS_GROWFS 14
> -#define XFS_TRANS_STRAT_WRITE 15
> -#define XFS_TRANS_DIOSTRAT 16
> -/* 17 was XFS_TRANS_WRITE_SYNC */
> -#define XFS_TRANS_WRITEID 18
> -#define XFS_TRANS_ADDAFORK 19
> -#define XFS_TRANS_ATTRINVAL 20
> -#define XFS_TRANS_ATRUNCATE 21
> -#define XFS_TRANS_ATTR_SET 22
> -#define XFS_TRANS_ATTR_RM 23
> -#define XFS_TRANS_ATTR_FLAG 24
> -#define XFS_TRANS_CLEAR_AGI_BUCKET 25
> -#define XFS_TRANS_QM_SBCHANGE 26
> -/*
> - * Dummy entries since we use the transaction type to index into the
> - * trans_type[] in xlog_recover_print_trans_head()
> - */
> -#define XFS_TRANS_DUMMY1 27
> -#define XFS_TRANS_DUMMY2 28
> -#define XFS_TRANS_QM_QUOTAOFF 29
> -#define XFS_TRANS_QM_DQALLOC 30
> -#define XFS_TRANS_QM_SETQLIM 31
> -#define XFS_TRANS_QM_DQCLUSTER 32
> -#define XFS_TRANS_QM_QINOCREATE 33
> -#define XFS_TRANS_QM_QUOTAOFF_END 34
> -#define XFS_TRANS_SB_UNIT 35
> -#define XFS_TRANS_FSYNC_TS 36
> -#define XFS_TRANS_GROWFSRT_ALLOC 37
> -#define XFS_TRANS_GROWFSRT_ZERO 38
> -#define XFS_TRANS_GROWFSRT_FREE 39
> -#define XFS_TRANS_SWAPEXT 40
> -#define XFS_TRANS_SB_COUNT 41
> -#define XFS_TRANS_CHECKPOINT 42
> -#define XFS_TRANS_ICREATE 43
> -#define XFS_TRANS_TYPE_MAX 43
> -/* new transaction types need to be reflected in xfs_logprint(8) */
> -
> -#define XFS_TRANS_TYPES \
> - { XFS_TRANS_SETATTR_NOT_SIZE, "SETATTR_NOT_SIZE" }, \
> - { XFS_TRANS_SETATTR_SIZE, "SETATTR_SIZE" }, \
> - { XFS_TRANS_INACTIVE, "INACTIVE" }, \
> - { XFS_TRANS_CREATE, "CREATE" }, \
> - { XFS_TRANS_CREATE_TRUNC, "CREATE_TRUNC" }, \
> - { XFS_TRANS_TRUNCATE_FILE, "TRUNCATE_FILE" }, \
> - { XFS_TRANS_REMOVE, "REMOVE" }, \
> - { XFS_TRANS_LINK, "LINK" }, \
> - { XFS_TRANS_RENAME, "RENAME" }, \
> - { XFS_TRANS_MKDIR, "MKDIR" }, \
> - { XFS_TRANS_RMDIR, "RMDIR" }, \
> - { XFS_TRANS_SYMLINK, "SYMLINK" }, \
> - { XFS_TRANS_SET_DMATTRS, "SET_DMATTRS" }, \
> - { XFS_TRANS_GROWFS, "GROWFS" }, \
> - { XFS_TRANS_STRAT_WRITE, "STRAT_WRITE" }, \
> - { XFS_TRANS_DIOSTRAT, "DIOSTRAT" }, \
> - { XFS_TRANS_WRITEID, "WRITEID" }, \
> - { XFS_TRANS_ADDAFORK, "ADDAFORK" }, \
> - { XFS_TRANS_ATTRINVAL, "ATTRINVAL" }, \
> - { XFS_TRANS_ATRUNCATE, "ATRUNCATE" }, \
> - { XFS_TRANS_ATTR_SET, "ATTR_SET" }, \
> - { XFS_TRANS_ATTR_RM, "ATTR_RM" }, \
> - { XFS_TRANS_ATTR_FLAG, "ATTR_FLAG" }, \
> - { XFS_TRANS_CLEAR_AGI_BUCKET, "CLEAR_AGI_BUCKET" }, \
> - { XFS_TRANS_QM_SBCHANGE, "QM_SBCHANGE" }, \
> - { XFS_TRANS_QM_QUOTAOFF, "QM_QUOTAOFF" }, \
> - { XFS_TRANS_QM_DQALLOC, "QM_DQALLOC" }, \
> - { XFS_TRANS_QM_SETQLIM, "QM_SETQLIM" }, \
> - { XFS_TRANS_QM_DQCLUSTER, "QM_DQCLUSTER" }, \
> - { XFS_TRANS_QM_QINOCREATE, "QM_QINOCREATE" }, \
> - { XFS_TRANS_QM_QUOTAOFF_END, "QM_QOFF_END" }, \
> - { XFS_TRANS_SB_UNIT, "SB_UNIT" }, \
> - { XFS_TRANS_FSYNC_TS, "FSYNC_TS" }, \
> - { XFS_TRANS_GROWFSRT_ALLOC, "GROWFSRT_ALLOC" }, \
> - { XFS_TRANS_GROWFSRT_ZERO, "GROWFSRT_ZERO" }, \
> - { XFS_TRANS_GROWFSRT_FREE, "GROWFSRT_FREE" }, \
> - { XFS_TRANS_SWAPEXT, "SWAPEXT" }, \
> - { XFS_TRANS_SB_COUNT, "SB_COUNT" }, \
> - { XFS_TRANS_CHECKPOINT, "CHECKPOINT" }, \
> - { XFS_TRANS_DUMMY1, "DUMMY1" }, \
> - { XFS_TRANS_DUMMY2, "DUMMY2" }, \
> - { XLOG_UNMOUNT_REC_TYPE, "UNMOUNT" }
> -
> -/*
> - * This structure is used to track log items associated with
> - * a transaction. It points to the log item and keeps some
> - * flags to track the state of the log item. It also tracks
> - * the amount of space needed to log the item it describes
> - * once we get to commit processing (see xfs_trans_commit()).
> - */
> -struct xfs_log_item_desc {
> - struct xfs_log_item *lid_item;
> - struct list_head lid_trans;
> - unsigned char lid_flags;
> -};
> -
> -#define XFS_LID_DIRTY 0x1
> -
> -/*
> - * Values for t_flags.
> - */
> -#define XFS_TRANS_DIRTY 0x01 /* something needs to be logged */
> -#define XFS_TRANS_SB_DIRTY 0x02 /* superblock is modified */
> -#define XFS_TRANS_PERM_LOG_RES 0x04 /* xact took a permanent log res */
> -#define XFS_TRANS_SYNC 0x08 /* make commit synchronous */
> -#define XFS_TRANS_DQ_DIRTY 0x10 /* at least one dquot in trx dirty */
> -#define XFS_TRANS_RESERVE 0x20 /* OK to use reserved data blocks */
> -#define XFS_TRANS_FREEZE_PROT 0x40 /* Transaction has elevated writer
> - count in superblock */
> -
> -/*
> - * Values for call flags parameter.
> - */
> -#define XFS_TRANS_RELEASE_LOG_RES 0x4
> -#define XFS_TRANS_ABORT 0x8
> -
> -/*
> - * Field values for xfs_trans_mod_sb.
> - */
> -#define XFS_TRANS_SB_ICOUNT 0x00000001
> -#define XFS_TRANS_SB_IFREE 0x00000002
> -#define XFS_TRANS_SB_FDBLOCKS 0x00000004
> -#define XFS_TRANS_SB_RES_FDBLOCKS 0x00000008
> -#define XFS_TRANS_SB_FREXTENTS 0x00000010
> -#define XFS_TRANS_SB_RES_FREXTENTS 0x00000020
> -#define XFS_TRANS_SB_DBLOCKS 0x00000040
> -#define XFS_TRANS_SB_AGCOUNT 0x00000080
> -#define XFS_TRANS_SB_IMAXPCT 0x00000100
> -#define XFS_TRANS_SB_REXTSIZE 0x00000200
> -#define XFS_TRANS_SB_RBMBLOCKS 0x00000400
> -#define XFS_TRANS_SB_RBLOCKS 0x00000800
> -#define XFS_TRANS_SB_REXTENTS 0x00001000
> -#define XFS_TRANS_SB_REXTSLOG 0x00002000
> -
> -/*
> - * Here we centralize the specification of XFS meta-data buffer
> - * reference count values. This determine how hard the buffer
> - * cache tries to hold onto the buffer.
> - */
> -#define XFS_AGF_REF 4
> -#define XFS_AGI_REF 4
> -#define XFS_AGFL_REF 3
> -#define XFS_INO_BTREE_REF 3
> -#define XFS_ALLOC_BTREE_REF 2
> -#define XFS_BMAP_BTREE_REF 2
> -#define XFS_DIR_BTREE_REF 2
> -#define XFS_INO_REF 2
> -#define XFS_ATTR_BTREE_REF 1
> -#define XFS_DQUOT_REF 1
> -
> -/*
> - * Flags for xfs_trans_ichgtime().
> - */
> -#define XFS_ICHGTIME_MOD 0x1 /* data fork modification timestamp */
> -#define XFS_ICHGTIME_CHG 0x2 /* inode field change timestamp */
> -#define XFS_ICHGTIME_CREATE 0x4 /* inode create timestamp */
> -
> -
> -/*
> * Inode Log Item Format definitions.
> *
> * This is the structure used to lay out an inode log item in the
> @@ -793,7 +621,6 @@ typedef struct xfs_qoff_logformat {
> char qf_pad[12]; /* padding for future */
> } xfs_qoff_logformat_t;
>
> -
> /*
> * Disk quotas status in m_qflags, and also sb_qflags. 16 bits.
> */
> @@ -845,8 +672,4 @@ struct xfs_icreate_log {
> __be32 icl_gen; /* inode generation number to use */
> };
>
> -int xfs_log_calc_unit_res(struct xfs_mount *mp, int unit_bytes);
> -int xfs_log_calc_minimum_size(struct xfs_mount *);
> -
> -
> #endif /* __XFS_LOG_FORMAT_H__ */
> diff --git a/include/xfs_sb.h b/include/xfs_sb.h
> index c8d8898..741b7a3 100644
> --- a/include/xfs_sb.h
> +++ b/include/xfs_sb.h
> @@ -695,7 +695,4 @@ extern void xfs_sb_from_disk(struct xfs_sb *, struct xfs_dsb *);
> extern void xfs_sb_to_disk(struct xfs_dsb *, struct xfs_sb *, __int64_t);
> extern void xfs_sb_quota_from_disk(struct xfs_sb *sbp);
>
> -extern const struct xfs_buf_ops xfs_sb_buf_ops;
> -extern const struct xfs_buf_ops xfs_sb_quiet_buf_ops;
> -
> #endif /* __XFS_SB_H__ */
> diff --git a/include/xfs_shared.h b/include/xfs_shared.h
> new file mode 100644
> index 0000000..63c94b1
> --- /dev/null
> +++ b/include/xfs_shared.h
> @@ -0,0 +1,244 @@
> +/*
> + * Copyright (c) 2000-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
> + */
> +#ifndef __XFS_SHARED_H__
> +#define __XFS_SHARED_H__
> +
> +/*
> + * Definitions shared between kernel and userspace that don't fit into any other
> + * header file that is shared with userspace.
> + */
> +struct xfs_ifork;
> +struct xfs_buf;
> +struct xfs_buf_ops;
> +struct xfs_mount;
> +struct xfs_trans;
> +struct xfs_inode;
> +
> +/*
> + * Buffer verifier operations are widely used, including userspace tools
> + */
> +extern const struct xfs_buf_ops xfs_agf_buf_ops;
> +extern const struct xfs_buf_ops xfs_agi_buf_ops;
> +extern const struct xfs_buf_ops xfs_agf_buf_ops;
> +extern const struct xfs_buf_ops xfs_agfl_buf_ops;
> +extern const struct xfs_buf_ops xfs_allocbt_buf_ops;
> +extern const struct xfs_buf_ops xfs_attr3_leaf_buf_ops;
> +extern const struct xfs_buf_ops xfs_attr3_rmt_buf_ops;
> +extern const struct xfs_buf_ops xfs_bmbt_buf_ops;
> +extern const struct xfs_buf_ops xfs_da3_node_buf_ops;
> +extern const struct xfs_buf_ops xfs_dquot_buf_ops;
> +extern const struct xfs_buf_ops xfs_symlink_buf_ops;
> +extern const struct xfs_buf_ops xfs_agi_buf_ops;
> +extern const struct xfs_buf_ops xfs_inobt_buf_ops;
> +extern const struct xfs_buf_ops xfs_inode_buf_ops;
> +extern const struct xfs_buf_ops xfs_inode_buf_ra_ops;
> +extern const struct xfs_buf_ops xfs_dquot_buf_ops;
> +extern const struct xfs_buf_ops xfs_sb_buf_ops;
> +extern const struct xfs_buf_ops xfs_sb_quiet_buf_ops;
> +extern const struct xfs_buf_ops xfs_symlink_buf_ops;
> +
> +/*
> + * Transaction types. Used to distinguish types of buffers. These never reach
> + * the log.
> + */
> +#define XFS_TRANS_SETATTR_NOT_SIZE 1
> +#define XFS_TRANS_SETATTR_SIZE 2
> +#define XFS_TRANS_INACTIVE 3
> +#define XFS_TRANS_CREATE 4
> +#define XFS_TRANS_CREATE_TRUNC 5
> +#define XFS_TRANS_TRUNCATE_FILE 6
> +#define XFS_TRANS_REMOVE 7
> +#define XFS_TRANS_LINK 8
> +#define XFS_TRANS_RENAME 9
> +#define XFS_TRANS_MKDIR 10
> +#define XFS_TRANS_RMDIR 11
> +#define XFS_TRANS_SYMLINK 12
> +#define XFS_TRANS_SET_DMATTRS 13
> +#define XFS_TRANS_GROWFS 14
> +#define XFS_TRANS_STRAT_WRITE 15
> +#define XFS_TRANS_DIOSTRAT 16
> +/* 17 was XFS_TRANS_WRITE_SYNC */
> +#define XFS_TRANS_WRITEID 18
> +#define XFS_TRANS_ADDAFORK 19
> +#define XFS_TRANS_ATTRINVAL 20
> +#define XFS_TRANS_ATRUNCATE 21
> +#define XFS_TRANS_ATTR_SET 22
> +#define XFS_TRANS_ATTR_RM 23
> +#define XFS_TRANS_ATTR_FLAG 24
> +#define XFS_TRANS_CLEAR_AGI_BUCKET 25
> +#define XFS_TRANS_QM_SBCHANGE 26
> +/*
> + * Dummy entries since we use the transaction type to index into the
> + * trans_type[] in xlog_recover_print_trans_head()
> + */
> +#define XFS_TRANS_DUMMY1 27
> +#define XFS_TRANS_DUMMY2 28
> +#define XFS_TRANS_QM_QUOTAOFF 29
> +#define XFS_TRANS_QM_DQALLOC 30
> +#define XFS_TRANS_QM_SETQLIM 31
> +#define XFS_TRANS_QM_DQCLUSTER 32
> +#define XFS_TRANS_QM_QINOCREATE 33
> +#define XFS_TRANS_QM_QUOTAOFF_END 34
> +#define XFS_TRANS_SB_UNIT 35
> +#define XFS_TRANS_FSYNC_TS 36
> +#define XFS_TRANS_GROWFSRT_ALLOC 37
> +#define XFS_TRANS_GROWFSRT_ZERO 38
> +#define XFS_TRANS_GROWFSRT_FREE 39
> +#define XFS_TRANS_SWAPEXT 40
> +#define XFS_TRANS_SB_COUNT 41
> +#define XFS_TRANS_CHECKPOINT 42
> +#define XFS_TRANS_ICREATE 43
> +#define XFS_TRANS_TYPE_MAX 43
> +/* new transaction types need to be reflected in xfs_logprint(8) */
> +
> +#define XFS_TRANS_TYPES \
> + { XFS_TRANS_SETATTR_NOT_SIZE, "SETATTR_NOT_SIZE" }, \
> + { XFS_TRANS_SETATTR_SIZE, "SETATTR_SIZE" }, \
> + { XFS_TRANS_INACTIVE, "INACTIVE" }, \
> + { XFS_TRANS_CREATE, "CREATE" }, \
> + { XFS_TRANS_CREATE_TRUNC, "CREATE_TRUNC" }, \
> + { XFS_TRANS_TRUNCATE_FILE, "TRUNCATE_FILE" }, \
> + { XFS_TRANS_REMOVE, "REMOVE" }, \
> + { XFS_TRANS_LINK, "LINK" }, \
> + { XFS_TRANS_RENAME, "RENAME" }, \
> + { XFS_TRANS_MKDIR, "MKDIR" }, \
> + { XFS_TRANS_RMDIR, "RMDIR" }, \
> + { XFS_TRANS_SYMLINK, "SYMLINK" }, \
> + { XFS_TRANS_SET_DMATTRS, "SET_DMATTRS" }, \
> + { XFS_TRANS_GROWFS, "GROWFS" }, \
> + { XFS_TRANS_STRAT_WRITE, "STRAT_WRITE" }, \
> + { XFS_TRANS_DIOSTRAT, "DIOSTRAT" }, \
> + { XFS_TRANS_WRITEID, "WRITEID" }, \
> + { XFS_TRANS_ADDAFORK, "ADDAFORK" }, \
> + { XFS_TRANS_ATTRINVAL, "ATTRINVAL" }, \
> + { XFS_TRANS_ATRUNCATE, "ATRUNCATE" }, \
> + { XFS_TRANS_ATTR_SET, "ATTR_SET" }, \
> + { XFS_TRANS_ATTR_RM, "ATTR_RM" }, \
> + { XFS_TRANS_ATTR_FLAG, "ATTR_FLAG" }, \
> + { XFS_TRANS_CLEAR_AGI_BUCKET, "CLEAR_AGI_BUCKET" }, \
> + { XFS_TRANS_QM_SBCHANGE, "QM_SBCHANGE" }, \
> + { XFS_TRANS_QM_QUOTAOFF, "QM_QUOTAOFF" }, \
> + { XFS_TRANS_QM_DQALLOC, "QM_DQALLOC" }, \
> + { XFS_TRANS_QM_SETQLIM, "QM_SETQLIM" }, \
> + { XFS_TRANS_QM_DQCLUSTER, "QM_DQCLUSTER" }, \
> + { XFS_TRANS_QM_QINOCREATE, "QM_QINOCREATE" }, \
> + { XFS_TRANS_QM_QUOTAOFF_END, "QM_QOFF_END" }, \
> + { XFS_TRANS_SB_UNIT, "SB_UNIT" }, \
> + { XFS_TRANS_FSYNC_TS, "FSYNC_TS" }, \
> + { XFS_TRANS_GROWFSRT_ALLOC, "GROWFSRT_ALLOC" }, \
> + { XFS_TRANS_GROWFSRT_ZERO, "GROWFSRT_ZERO" }, \
> + { XFS_TRANS_GROWFSRT_FREE, "GROWFSRT_FREE" }, \
> + { XFS_TRANS_SWAPEXT, "SWAPEXT" }, \
> + { XFS_TRANS_SB_COUNT, "SB_COUNT" }, \
> + { XFS_TRANS_CHECKPOINT, "CHECKPOINT" }, \
> + { XFS_TRANS_DUMMY1, "DUMMY1" }, \
> + { XFS_TRANS_DUMMY2, "DUMMY2" }, \
> + { XLOG_UNMOUNT_REC_TYPE, "UNMOUNT" }
> +
> +/*
> + * This structure is used to track log items associated with
> + * a transaction. It points to the log item and keeps some
> + * flags to track the state of the log item. It also tracks
> + * the amount of space needed to log the item it describes
> + * once we get to commit processing (see xfs_trans_commit()).
> + */
> +struct xfs_log_item_desc {
> + struct xfs_log_item *lid_item;
> + struct list_head lid_trans;
> + unsigned char lid_flags;
> +};
> +
> +#define XFS_LID_DIRTY 0x1
> +
> +/* log size calculation functions */
> +int xfs_log_calc_unit_res(struct xfs_mount *mp, int unit_bytes);
> +int xfs_log_calc_minimum_size(struct xfs_mount *);
> +
> +
> +/*
> + * Values for t_flags.
> + */
> +#define XFS_TRANS_DIRTY 0x01 /* something needs to be logged */
> +#define XFS_TRANS_SB_DIRTY 0x02 /* superblock is modified */
> +#define XFS_TRANS_PERM_LOG_RES 0x04 /* xact took a permanent log res */
> +#define XFS_TRANS_SYNC 0x08 /* make commit synchronous */
> +#define XFS_TRANS_DQ_DIRTY 0x10 /* at least one dquot in trx dirty */
> +#define XFS_TRANS_RESERVE 0x20 /* OK to use reserved data blocks */
> +#define XFS_TRANS_FREEZE_PROT 0x40 /* Transaction has elevated writer
> + count in superblock */
> +/*
> + * Values for call flags parameter.
> + */
> +#define XFS_TRANS_RELEASE_LOG_RES 0x4
> +#define XFS_TRANS_ABORT 0x8
> +
> +/*
> + * Field values for xfs_trans_mod_sb.
> + */
> +#define XFS_TRANS_SB_ICOUNT 0x00000001
> +#define XFS_TRANS_SB_IFREE 0x00000002
> +#define XFS_TRANS_SB_FDBLOCKS 0x00000004
> +#define XFS_TRANS_SB_RES_FDBLOCKS 0x00000008
> +#define XFS_TRANS_SB_FREXTENTS 0x00000010
> +#define XFS_TRANS_SB_RES_FREXTENTS 0x00000020
> +#define XFS_TRANS_SB_DBLOCKS 0x00000040
> +#define XFS_TRANS_SB_AGCOUNT 0x00000080
> +#define XFS_TRANS_SB_IMAXPCT 0x00000100
> +#define XFS_TRANS_SB_REXTSIZE 0x00000200
> +#define XFS_TRANS_SB_RBMBLOCKS 0x00000400
> +#define XFS_TRANS_SB_RBLOCKS 0x00000800
> +#define XFS_TRANS_SB_REXTENTS 0x00001000
> +#define XFS_TRANS_SB_REXTSLOG 0x00002000
> +
> +/*
> + * Here we centralize the specification of XFS meta-data buffer reference count
> + * values. This determine how hard the buffer cache tries to hold onto the
> + * buffer.
> + */
> +#define XFS_AGF_REF 4
> +#define XFS_AGI_REF 4
> +#define XFS_AGFL_REF 3
> +#define XFS_INO_BTREE_REF 3
> +#define XFS_ALLOC_BTREE_REF 2
> +#define XFS_BMAP_BTREE_REF 2
> +#define XFS_DIR_BTREE_REF 2
> +#define XFS_INO_REF 2
> +#define XFS_ATTR_BTREE_REF 1
> +#define XFS_DQUOT_REF 1
> +
> +/*
> + * Flags for xfs_trans_ichgtime().
> + */
> +#define XFS_ICHGTIME_MOD 0x1 /* data fork modification timestamp */
> +#define XFS_ICHGTIME_CHG 0x2 /* inode field change timestamp */
> +#define XFS_ICHGTIME_CREATE 0x4 /* inode create timestamp */
> +
> +
> +/*
> + * Symlink decoding/encoding functions
> + */
> +int xfs_symlink_blocks(struct xfs_mount *mp, int pathlen);
> +int xfs_symlink_hdr_set(struct xfs_mount *mp, xfs_ino_t ino, uint32_t offset,
> + uint32_t size, struct xfs_buf *bp);
> +bool xfs_symlink_hdr_ok(struct xfs_mount *mp, xfs_ino_t ino, uint32_t offset,
> + uint32_t size, struct xfs_buf *bp);
> +void xfs_symlink_local_to_remote(struct xfs_trans *tp, struct xfs_buf *bp,
> + struct xfs_inode *ip, struct xfs_ifork *ifp);
> +
> +#endif /* __XFS_SHARED_H__ */
>
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [PATCH 02/32] libxfs: fix missing filetype updates to xfs_dir2.c
2013-10-08 22:53 ` Eric Sandeen
@ 2013-10-09 20:41 ` Dave Chinner
0 siblings, 0 replies; 56+ messages in thread
From: Dave Chinner @ 2013-10-09 20:41 UTC (permalink / raw)
To: Eric Sandeen; +Cc: xfs
On Tue, Oct 08, 2013 at 05:53:38PM -0500, Eric Sandeen wrote:
> On 9/29/13 10:15 PM, Dave Chinner wrote:
> > From: Dave Chinner <dchinner@redhat.com>
> >
> > They were missed in the original patch that was committed.
>
> I'm not sure it's required in lookup or remove, at least today
> nothing looks at it on those paths, does it?
Correct, but...
> Anyway, matches kernel, at worst the last 2 are harmless:
... matching the kernel code is more important at this point.
> Reviewed-by: Eric Sandeen <sandeen@redhat.com>
Thanks,
Dave.
--
Dave Chinner
david@fromorbit.com
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [PATCH 03/32] xfs: fix some minor sparse warnings
2013-10-08 22:56 ` Eric Sandeen
@ 2013-10-09 20:43 ` Dave Chinner
0 siblings, 0 replies; 56+ messages in thread
From: Dave Chinner @ 2013-10-09 20:43 UTC (permalink / raw)
To: Eric Sandeen; +Cc: xfs
On Tue, Oct 08, 2013 at 05:56:00PM -0500, Eric Sandeen wrote:
> On 9/29/13 10:15 PM, Dave Chinner wrote:
> > From: Dave Chinner <dchinner@redhat.com>
> >
> > A couple of simple locking annotations and 0 vs NULL warnings.
> > Nothing that changes any code behaviour, just removes build noise.
>
> The patch is fine as it is, but it doesn't reflect the commit log.
>
> Is part of it missing?
It's trimmed down from the kernel commit to just the bits that are
in libxfs. I haven't altered it in any other way, so it's entirely
possible the commit message has bits in it that the patch now
doesn't.
Cheers,
Dave.
--
Dave Chinner
david@fromorbit.com
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [PATCH 04/32] xfs: check magic numbers in dir3 leaf verifier first
2013-10-08 23:03 ` Eric Sandeen
@ 2013-10-09 20:45 ` Dave Chinner
2013-10-09 20:50 ` Eric Sandeen
0 siblings, 1 reply; 56+ messages in thread
From: Dave Chinner @ 2013-10-09 20:45 UTC (permalink / raw)
To: Eric Sandeen; +Cc: xfs
On Tue, Oct 08, 2013 at 06:03:43PM -0500, Eric Sandeen wrote:
> On 9/29/13 10:15 PM, Dave Chinner wrote:
> > From: Dave Chinner <dchinner@redhat.com>
> >
> > Calling xfs_dir3_leaf_hdr_from_disk() in a verifier before
> > validating the magic numbers in the buffer results in ASSERT
> > failures due to mismatching magic numbers when a corruption occurs.
> > Seeing as the verifier is supposed to catch the corruption and pass
> > it back to the caller, having the verifier assert fail on error
> > defeats the purpose of detecting the errors in the first place.
> >
> > Check the magic numbers direct from the buffer before decoding the
> > header.
>
> Looks good; have you sent this for the kernel yet?
>
> (I thought we wanted changes to hit kernelspace first) :)
Yes, commit 0f295a214bb7658ca37bd61a8a1f0cd4a9d86c1f.
Cheers,
Dave.
--
Dave Chinner
david@fromorbit.com
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [PATCH 04/32] xfs: check magic numbers in dir3 leaf verifier first
2013-10-09 20:45 ` Dave Chinner
@ 2013-10-09 20:50 ` Eric Sandeen
0 siblings, 0 replies; 56+ messages in thread
From: Eric Sandeen @ 2013-10-09 20:50 UTC (permalink / raw)
To: Dave Chinner; +Cc: xfs
On 10/9/13 3:45 PM, Dave Chinner wrote:
> On Tue, Oct 08, 2013 at 06:03:43PM -0500, Eric Sandeen wrote:
>> On 9/29/13 10:15 PM, Dave Chinner wrote:
>>> From: Dave Chinner <dchinner@redhat.com>
>>>
>>> Calling xfs_dir3_leaf_hdr_from_disk() in a verifier before
>>> validating the magic numbers in the buffer results in ASSERT
>>> failures due to mismatching magic numbers when a corruption occurs.
>>> Seeing as the verifier is supposed to catch the corruption and pass
>>> it back to the caller, having the verifier assert fail on error
>>> defeats the purpose of detecting the errors in the first place.
>>>
>>> Check the magic numbers direct from the buffer before decoding the
>>> header.
>>
>> Looks good; have you sent this for the kernel yet?
>>
>> (I thought we wanted changes to hit kernelspace first) :)
>
> Yes, commit 0f295a214bb7658ca37bd61a8a1f0cd4a9d86c1f.
Sorry I missed that, man, I swear I looked.
-Eric
> Cheers,
>
> Dave.
>
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [PATCH 07/32] xfs: dirent dtype presence is dependent on directory magic numbers
2013-10-08 23:30 ` Eric Sandeen
@ 2013-10-09 20:51 ` Dave Chinner
2013-10-09 20:57 ` Eric Sandeen
2013-10-18 22:38 ` Rich Johnston
1 sibling, 1 reply; 56+ messages in thread
From: Dave Chinner @ 2013-10-09 20:51 UTC (permalink / raw)
To: Eric Sandeen; +Cc: xfs
On Tue, Oct 08, 2013 at 06:30:43PM -0500, Eric Sandeen wrote:
> On 9/29/13 10:15 PM, Dave Chinner wrote:
> > From: Dave Chinner <dchinner@redhat.com>
> >
> > The determination of whether a directory entry contains a dtype
> > field originally was dependent on the filesystem having CRCs
> > enabled. This meant that the format for dtype beign enabled could be
> > determined by checking the directory block magic number rather than
> > doing a feature bit check. This was useful in that it meant that we
> > didn't need to pass a struct xfs_mount around to functions that
> > were already supplied with a directory block header.
> >
> > Unfortunately, the introduction of dtype fields into the v4
> > structure via a feature bit meant this "use the directory block
> > magic number" method of discriminating the dirent entry sizes is
> > broken. Hence we need to convert the places that use magic number
> > checks to use feature bit checks so that they work correctly and not
> > by chance.
> >
> > The current code works on v4 filesystems only because the dirent
> > size roundup covers the extra byte needed by the dtype field in the
> > places where this problem occurs.
>
> Looks right to me. Nitpicks & questions though:
>
> FWIW, I find it confusing that we call xfs_dir3_*()
> functions from dir2 code or to find out whether the
> dir is in fact dir2 or dir3.
>
> i.e.:
>
> return xfs_dir3_data_hdr_size(xfs_sb_version_hascrc(&mp->m_sb));
It's the convention I've used since first introducing the CRC code.
dir2 means it handles just dir2 format, dir3 means it handles either
the dir2 or the CRC enabled format.
That said, this goes away in the directory ops vectorisation patch
set, when dir2 means "handles dir2 format" and dir3 means "handles
only dir3 format"....
> that just seems like an odd name to calculate the header size for
> dir2 vs. dir3 directories.
>
> Also -
>
> Is there any pro or con to defining the 3 offsets recursively:
>
> static inline xfs_dir2_data_aoff_t
> xfs_dir3_data_dot_offset(struct xfs_mount *mp)
> {
> return xfs_dir3_data_hdr_size(xfs_sb_version_hascrc(&mp->m_sb));
> }
>
> static inline xfs_dir2_data_aoff_t
> xfs_dir3_data_dotdot_offset(struct xfs_mount *mp)
> {
> return xfs_dir3_data_dot_offset(mp) +
> xfs_dir3_data_entsize(mp, 1);
> }
>
> static inline xfs_dir2_data_aoff_t
> xfs_dir3_data_first_offset(struct xfs_mount *mp)
> {
> return xfs_dir3_data_dotdot_offset(mp) +
> xfs_dir3_data_entsize(mp, 2);
> }
>
> vs directly, i.e.:
>
> static inline xfs_dir2_data_aoff_t
> xfs_dir3_data_first_offset(struct xfs_mount *mp)
> {
> return xfs_dir3_data_hdr_size(xfs_sb_version_hascrc(&mp->m_sb)) +
> xfs_dir3_data_entsize(mp, 1); /* Dot */
> xfs_dir3_data_entsize(mp, 2); /* Dotdot */
> }
None, really. This is just a mechanical change to fix the bug, not a
change of logic. This is changed to the direct method in the dir ops
vectorisation series....
Cheers,
Dave.
--
Dave Chinner
david@fromorbit.com
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [PATCH 07/32] xfs: dirent dtype presence is dependent on directory magic numbers
2013-10-09 20:51 ` Dave Chinner
@ 2013-10-09 20:57 ` Eric Sandeen
0 siblings, 0 replies; 56+ messages in thread
From: Eric Sandeen @ 2013-10-09 20:57 UTC (permalink / raw)
To: Dave Chinner; +Cc: xfs
On 10/9/13 3:51 PM, Dave Chinner wrote:
> On Tue, Oct 08, 2013 at 06:30:43PM -0500, Eric Sandeen wrote:
>> On 9/29/13 10:15 PM, Dave Chinner wrote:
>>> From: Dave Chinner <dchinner@redhat.com>
>>>
>>> The determination of whether a directory entry contains a dtype
>>> field originally was dependent on the filesystem having CRCs
>>> enabled. This meant that the format for dtype beign enabled could be
>>> determined by checking the directory block magic number rather than
>>> doing a feature bit check. This was useful in that it meant that we
>>> didn't need to pass a struct xfs_mount around to functions that
>>> were already supplied with a directory block header.
>>>
>>> Unfortunately, the introduction of dtype fields into the v4
>>> structure via a feature bit meant this "use the directory block
>>> magic number" method of discriminating the dirent entry sizes is
>>> broken. Hence we need to convert the places that use magic number
>>> checks to use feature bit checks so that they work correctly and not
>>> by chance.
>>>
>>> The current code works on v4 filesystems only because the dirent
>>> size roundup covers the extra byte needed by the dtype field in the
>>> places where this problem occurs.
>>
>> Looks right to me. Nitpicks & questions though:
>>
>> FWIW, I find it confusing that we call xfs_dir3_*()
>> functions from dir2 code or to find out whether the
>> dir is in fact dir2 or dir3.
>>
>> i.e.:
>>
>> return xfs_dir3_data_hdr_size(xfs_sb_version_hascrc(&mp->m_sb));
>
> It's the convention I've used since first introducing the CRC code.
> dir2 means it handles just dir2 format, dir3 means it handles either
> the dir2 or the CRC enabled format.
>
> That said, this goes away in the directory ops vectorisation patch
> set, when dir2 means "handles dir2 format" and dir3 means "handles
> only dir3 format"....
>
>> that just seems like an odd name to calculate the header size for
>> dir2 vs. dir3 directories.
>>
>> Also -
>>
>> Is there any pro or con to defining the 3 offsets recursively:
>>
>> static inline xfs_dir2_data_aoff_t
>> xfs_dir3_data_dot_offset(struct xfs_mount *mp)
>> {
>> return xfs_dir3_data_hdr_size(xfs_sb_version_hascrc(&mp->m_sb));
>> }
>>
>> static inline xfs_dir2_data_aoff_t
>> xfs_dir3_data_dotdot_offset(struct xfs_mount *mp)
>> {
>> return xfs_dir3_data_dot_offset(mp) +
>> xfs_dir3_data_entsize(mp, 1);
>> }
>>
>> static inline xfs_dir2_data_aoff_t
>> xfs_dir3_data_first_offset(struct xfs_mount *mp)
>> {
>> return xfs_dir3_data_dotdot_offset(mp) +
>> xfs_dir3_data_entsize(mp, 2);
>> }
>>
>> vs directly, i.e.:
>>
>> static inline xfs_dir2_data_aoff_t
>> xfs_dir3_data_first_offset(struct xfs_mount *mp)
>> {
>> return xfs_dir3_data_hdr_size(xfs_sb_version_hascrc(&mp->m_sb)) +
>> xfs_dir3_data_entsize(mp, 1); /* Dot */
>> xfs_dir3_data_entsize(mp, 2); /* Dotdot */
>> }
>
> None, really. This is just a mechanical change to fix the bug, not a
> change of logic. This is changed to the direct method in the dir ops
> vectorisation series....
Ok. Sorry for not keeping up.
(I knew it was mechanical, didn't mean this patch was wrong, just wondering
out loud some more).
-Eric
> Cheers,
>
> Dave.
>
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [PATCH 09/32] xfs: unify directory/attribute format definitions
2013-09-30 3:15 ` [PATCH 09/32] xfs: unify directory/attribute format definitions Dave Chinner
@ 2013-10-14 20:44 ` Eric Sandeen
2013-10-18 20:32 ` Rich Johnston
1 sibling, 0 replies; 56+ messages in thread
From: Eric Sandeen @ 2013-10-14 20:44 UTC (permalink / raw)
To: Dave Chinner; +Cc: xfs
On 9/29/13 10:15 PM, Dave Chinner wrote:
> From: Dave Chinner <dchinner@redhat.com>
>
> The on-disk format definitions for the directory and attribute
> structures are spread across 3 header files right now, only one of
> which is dedicated to defining on-disk structures and their
> manipulation (xfs_dir2_format.h). Pull all the format definitions
> into a single header file - xfs_da_format.h - and switch all the
> code over to point at that.
>
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
> ---
> include/Makefile | 4 +-
> include/libxfs.h | 6 +-
> include/xfs_attr_leaf.h | 230 --------
> include/xfs_attr_remote.h | 27 -
> include/xfs_da_btree.h | 140 -----
> include/xfs_da_format.h | 1362 +++++++++++++++++++++++++++++++++++++++++++++
> include/xfs_dir2_format.h | 964 --------------------------------
> 7 files changed, 1368 insertions(+), 1365 deletions(-)
> create mode 100644 include/xfs_da_format.h
> delete mode 100644 include/xfs_dir2_format.h
>
> diff --git a/include/Makefile b/include/Makefile
> index fd2d61b..6682b9d 100644
> --- a/include/Makefile
> +++ b/include/Makefile
> @@ -26,7 +26,9 @@ QAHFILES = libxfs.h libxlog.h \
> xfs_btree_trace.h \
> xfs_cksum.h \
> xfs_da_btree.h \
> - xfs_dinode.h xfs_dir2.h xfs_dir2_format.h \
> + xfs_da_format.h \
> + xfs_dinode.h \
> + xfs_dir2.h \
> xfs_format.h \
> xfs_ialloc.h \
> xfs_ialloc_btree.h \
> diff --git a/include/libxfs.h b/include/libxfs.h
> index a5d6388..835ba37 100644
> --- a/include/libxfs.h
> +++ b/include/libxfs.h
> @@ -47,7 +47,6 @@
> #include <xfs/xfs_inum.h>
> #include <xfs/xfs_sb.h>
> #include <xfs/xfs_ag.h>
> -#include <xfs/xfs_da_btree.h>
> #include <xfs/xfs_bmap_btree.h>
> #include <xfs/xfs_alloc_btree.h>
> #include <xfs/xfs_ialloc_btree.h>
> @@ -267,9 +266,10 @@ extern void libxfs_umount (xfs_mount_t *);
> extern void libxfs_rtmount_destroy (xfs_mount_t *);
>
> /*
> - * xfs/xfs_dir2_format.h needs struct xfs_mount to be defined
> + * xfs/xfs_da_format.h needs struct xfs_mount to be defined
> */
> -#include <xfs/xfs_dir2_format.h>
> +#include <xfs/xfs_da_format.h>
> +#include <xfs/xfs_da_btree.h>
> #include <xfs/xfs_dir2.h>
>
> /*
> diff --git a/include/xfs_attr_leaf.h b/include/xfs_attr_leaf.h
> index da34e64..3ec5ec0 100644
> --- a/include/xfs_attr_leaf.h
> +++ b/include/xfs_attr_leaf.h
> @@ -19,16 +19,6 @@
> #ifndef __XFS_ATTR_LEAF_H__
> #define __XFS_ATTR_LEAF_H__
>
> -/*
> - * Attribute storage layout, internal structure, access macros, etc.
> - *
> - * Attribute lists are structured around Btrees where all the data
> - * elements are in the leaf nodes. Attribute names are hashed into an int,
> - * then that int is used as the index into the Btree. Since the hashval
> - * of an attribute name may not be unique, we may have duplicate keys. The
> - * internal links in the Btree are logical block offsets into the file.
> - */
> -
> struct attrlist;
> struct attrlist_cursor_kern;
> struct xfs_attr_list_context;
> @@ -38,226 +28,6 @@ struct xfs_da_state_blk;
> struct xfs_inode;
> struct xfs_trans;
>
> -/*========================================================================
> - * Attribute structure when equal to XFS_LBSIZE(mp) bytes.
> - *========================================================================*/
> -
> -/*
> - * This is the structure of the leaf nodes in the Btree.
> - *
> - * Struct leaf_entry's are packed from the top. Name/values grow from the
> - * bottom but are not packed. The freemap contains run-length-encoded entries
> - * for the free bytes after the leaf_entry's, but only the N largest such,
> - * smaller runs are dropped. When the freemap doesn't show enough space
> - * for an allocation, we compact the name/value area and try again. If we
> - * still don't have enough space, then we have to split the block. The
> - * name/value structs (both local and remote versions) must be 32bit aligned.
> - *
> - * Since we have duplicate hash keys, for each key that matches, compare
> - * the actual name string. The root and intermediate node search always
> - * takes the first-in-the-block key match found, so we should only have
> - * to work "forw"ard. If none matches, continue with the "forw"ard leaf
> - * nodes until the hash key changes or the attribute name is found.
> - *
> - * We store the fact that an attribute is a ROOT/USER/SECURE attribute in
> - * the leaf_entry. The namespaces are independent only because we also look
> - * at the namespace bit when we are looking for a matching attribute name.
> - *
> - * We also store an "incomplete" bit in the leaf_entry. It shows that an
> - * attribute is in the middle of being created and should not be shown to
> - * the user if we crash during the time that the bit is set. We clear the
> - * bit when we have finished setting up the attribute. We do this because
> - * we cannot create some large attributes inside a single transaction, and we
> - * need some indication that we weren't finished if we crash in the middle.
> - */
> -#define XFS_ATTR_LEAF_MAPSIZE 3 /* how many freespace slots */
> -
> -typedef struct xfs_attr_leaf_map { /* RLE map of free bytes */
> - __be16 base; /* base of free region */
> - __be16 size; /* length of free region */
> -} xfs_attr_leaf_map_t;
> -
> -typedef struct xfs_attr_leaf_hdr { /* constant-structure header block */
> - xfs_da_blkinfo_t info; /* block type, links, etc. */
> - __be16 count; /* count of active leaf_entry's */
> - __be16 usedbytes; /* num bytes of names/values stored */
> - __be16 firstused; /* first used byte in name area */
> - __u8 holes; /* != 0 if blk needs compaction */
> - __u8 pad1;
> - xfs_attr_leaf_map_t freemap[XFS_ATTR_LEAF_MAPSIZE];
> - /* N largest free regions */
> -} xfs_attr_leaf_hdr_t;
> -
> -typedef struct xfs_attr_leaf_entry { /* sorted on key, not name */
> - __be32 hashval; /* hash value of name */
> - __be16 nameidx; /* index into buffer of name/value */
> - __u8 flags; /* LOCAL/ROOT/SECURE/INCOMPLETE flag */
> - __u8 pad2; /* unused pad byte */
> -} xfs_attr_leaf_entry_t;
> -
> -typedef struct xfs_attr_leaf_name_local {
> - __be16 valuelen; /* number of bytes in value */
> - __u8 namelen; /* length of name bytes */
> - __u8 nameval[1]; /* name/value bytes */
> -} xfs_attr_leaf_name_local_t;
> -
> -typedef struct xfs_attr_leaf_name_remote {
> - __be32 valueblk; /* block number of value bytes */
> - __be32 valuelen; /* number of bytes in value */
> - __u8 namelen; /* length of name bytes */
> - __u8 name[1]; /* name bytes */
> -} xfs_attr_leaf_name_remote_t;
> -
> -typedef struct xfs_attr_leafblock {
> - xfs_attr_leaf_hdr_t hdr; /* constant-structure header block */
> - xfs_attr_leaf_entry_t entries[1]; /* sorted on key, not name */
> - xfs_attr_leaf_name_local_t namelist; /* grows from bottom of buf */
> - xfs_attr_leaf_name_remote_t valuelist; /* grows from bottom of buf */
> -} xfs_attr_leafblock_t;
> -
> -/*
> - * CRC enabled leaf structures. Called "version 3" structures to match the
> - * version number of the directory and dablk structures for this feature, and
> - * attr2 is already taken by the variable inode attribute fork size feature.
> - */
> -struct xfs_attr3_leaf_hdr {
> - struct xfs_da3_blkinfo info;
> - __be16 count;
> - __be16 usedbytes;
> - __be16 firstused;
> - __u8 holes;
> - __u8 pad1;
> - struct xfs_attr_leaf_map freemap[XFS_ATTR_LEAF_MAPSIZE];
> - __be32 pad2; /* 64 bit alignment */
> -};
> -
> -#define XFS_ATTR3_LEAF_CRC_OFF (offsetof(struct xfs_attr3_leaf_hdr, info.crc))
> -
> -struct xfs_attr3_leafblock {
> - struct xfs_attr3_leaf_hdr hdr;
> - struct xfs_attr_leaf_entry entries[1];
> -
> - /*
> - * The rest of the block contains the following structures after the
> - * leaf entries, growing from the bottom up. The variables are never
> - * referenced, the locations accessed purely from helper functions.
> - *
> - * struct xfs_attr_leaf_name_local
> - * struct xfs_attr_leaf_name_remote
> - */
> -};
> -
> -/*
> - * incore, neutral version of the attribute leaf header
> - */
> -struct xfs_attr3_icleaf_hdr {
> - __uint32_t forw;
> - __uint32_t back;
> - __uint16_t magic;
> - __uint16_t count;
> - __uint16_t usedbytes;
> - __uint16_t firstused;
> - __u8 holes;
> - struct {
> - __uint16_t base;
> - __uint16_t size;
> - } freemap[XFS_ATTR_LEAF_MAPSIZE];
> -};
> -
> -/*
> - * Flags used in the leaf_entry[i].flags field.
> - * NOTE: the INCOMPLETE bit must not collide with the flags bits specified
> - * on the system call, they are "or"ed together for various operations.
> - */
> -#define XFS_ATTR_LOCAL_BIT 0 /* attr is stored locally */
> -#define XFS_ATTR_ROOT_BIT 1 /* limit access to trusted attrs */
> -#define XFS_ATTR_SECURE_BIT 2 /* limit access to secure attrs */
> -#define XFS_ATTR_INCOMPLETE_BIT 7 /* attr in middle of create/delete */
> -#define XFS_ATTR_LOCAL (1 << XFS_ATTR_LOCAL_BIT)
> -#define XFS_ATTR_ROOT (1 << XFS_ATTR_ROOT_BIT)
> -#define XFS_ATTR_SECURE (1 << XFS_ATTR_SECURE_BIT)
> -#define XFS_ATTR_INCOMPLETE (1 << XFS_ATTR_INCOMPLETE_BIT)
> -
> -/*
> - * Conversion macros for converting namespace bits from argument flags
> - * to ondisk flags.
> - */
> -#define XFS_ATTR_NSP_ARGS_MASK (ATTR_ROOT | ATTR_SECURE)
> -#define XFS_ATTR_NSP_ONDISK_MASK (XFS_ATTR_ROOT | XFS_ATTR_SECURE)
> -#define XFS_ATTR_NSP_ONDISK(flags) ((flags) & XFS_ATTR_NSP_ONDISK_MASK)
> -#define XFS_ATTR_NSP_ARGS(flags) ((flags) & XFS_ATTR_NSP_ARGS_MASK)
> -#define XFS_ATTR_NSP_ARGS_TO_ONDISK(x) (((x) & ATTR_ROOT ? XFS_ATTR_ROOT : 0) |\
> - ((x) & ATTR_SECURE ? XFS_ATTR_SECURE : 0))
> -#define XFS_ATTR_NSP_ONDISK_TO_ARGS(x) (((x) & XFS_ATTR_ROOT ? ATTR_ROOT : 0) |\
> - ((x) & XFS_ATTR_SECURE ? ATTR_SECURE : 0))
> -
> -/*
> - * Alignment for namelist and valuelist entries (since they are mixed
> - * there can be only one alignment value)
> - */
> -#define XFS_ATTR_LEAF_NAME_ALIGN ((uint)sizeof(xfs_dablk_t))
> -
> -static inline int
> -xfs_attr3_leaf_hdr_size(struct xfs_attr_leafblock *leafp)
> -{
> - if (leafp->hdr.info.magic == cpu_to_be16(XFS_ATTR3_LEAF_MAGIC))
> - return sizeof(struct xfs_attr3_leaf_hdr);
> - return sizeof(struct xfs_attr_leaf_hdr);
> -}
> -
> -static inline struct xfs_attr_leaf_entry *
> -xfs_attr3_leaf_entryp(xfs_attr_leafblock_t *leafp)
> -{
> - if (leafp->hdr.info.magic == cpu_to_be16(XFS_ATTR3_LEAF_MAGIC))
> - return &((struct xfs_attr3_leafblock *)leafp)->entries[0];
> - return &leafp->entries[0];
> -}
> -
> -/*
> - * Cast typed pointers for "local" and "remote" name/value structs.
> - */
> -static inline char *
> -xfs_attr3_leaf_name(xfs_attr_leafblock_t *leafp, int idx)
> -{
> - struct xfs_attr_leaf_entry *entries = xfs_attr3_leaf_entryp(leafp);
> -
> - return &((char *)leafp)[be16_to_cpu(entries[idx].nameidx)];
> -}
> -
> -static inline xfs_attr_leaf_name_remote_t *
> -xfs_attr3_leaf_name_remote(xfs_attr_leafblock_t *leafp, int idx)
> -{
> - return (xfs_attr_leaf_name_remote_t *)xfs_attr3_leaf_name(leafp, idx);
> -}
> -
> -static inline xfs_attr_leaf_name_local_t *
> -xfs_attr3_leaf_name_local(xfs_attr_leafblock_t *leafp, int idx)
> -{
> - return (xfs_attr_leaf_name_local_t *)xfs_attr3_leaf_name(leafp, idx);
> -}
> -
> -/*
> - * Calculate total bytes used (including trailing pad for alignment) for
> - * a "local" name/value structure, a "remote" name/value structure, and
> - * a pointer which might be either.
> - */
> -static inline int xfs_attr_leaf_entsize_remote(int nlen)
> -{
> - return ((uint)sizeof(xfs_attr_leaf_name_remote_t) - 1 + (nlen) + \
> - XFS_ATTR_LEAF_NAME_ALIGN - 1) & ~(XFS_ATTR_LEAF_NAME_ALIGN - 1);
> -}
> -
> -static inline int xfs_attr_leaf_entsize_local(int nlen, int vlen)
> -{
> - return ((uint)sizeof(xfs_attr_leaf_name_local_t) - 1 + (nlen) + (vlen) +
> - XFS_ATTR_LEAF_NAME_ALIGN - 1) & ~(XFS_ATTR_LEAF_NAME_ALIGN - 1);
> -}
> -
> -static inline int xfs_attr_leaf_entsize_local_max(int bsize)
> -{
> - return (((bsize) >> 1) + ((bsize) >> 2));
> -}
> -
> /*
> * Used to keep a list of "remote value" extents when unlinking an inode.
> */
> diff --git a/include/xfs_attr_remote.h b/include/xfs_attr_remote.h
> index b3e1e1b..5a9acfa 100644
> --- a/include/xfs_attr_remote.h
> +++ b/include/xfs_attr_remote.h
> @@ -18,33 +18,6 @@
> #ifndef __XFS_ATTR_REMOTE_H__
> #define __XFS_ATTR_REMOTE_H__
>
> -#define XFS_ATTR3_RMT_MAGIC 0x5841524d /* XARM */
> -
> -/*
> - * There is one of these headers per filesystem block in a remote attribute.
> - * This is done to ensure there is a 1:1 mapping between the attribute value
> - * length and the number of blocks needed to store the attribute. This makes the
> - * verification of a buffer a little more complex, but greatly simplifies the
> - * allocation, reading and writing of these attributes as we don't have to guess
> - * the number of blocks needed to store the attribute data.
> - */
> -struct xfs_attr3_rmt_hdr {
> - __be32 rm_magic;
> - __be32 rm_offset;
> - __be32 rm_bytes;
> - __be32 rm_crc;
> - uuid_t rm_uuid;
> - __be64 rm_owner;
> - __be64 rm_blkno;
> - __be64 rm_lsn;
> -};
> -
> -#define XFS_ATTR3_RMT_CRC_OFF offsetof(struct xfs_attr3_rmt_hdr, rm_crc)
> -
> -#define XFS_ATTR3_RMT_BUF_SPACE(mp, bufsize) \
> - ((bufsize) - (xfs_sb_version_hascrc(&(mp)->m_sb) ? \
> - sizeof(struct xfs_attr3_rmt_hdr) : 0))
> -
> int xfs_attr3_rmt_blocks(struct xfs_mount *mp, int attrlen);
>
> int xfs_attr_rmtval_get(struct xfs_da_args *args);
> diff --git a/include/xfs_da_btree.h b/include/xfs_da_btree.h
> index a762cfa..e492dca 100644
> --- a/include/xfs_da_btree.h
> +++ b/include/xfs_da_btree.h
> @@ -25,146 +25,6 @@ struct xfs_trans;
> struct zone;
>
> /*========================================================================
> - * Directory Structure when greater than XFS_LBSIZE(mp) bytes.
> - *========================================================================*/
> -
> -/*
> - * This structure is common to both leaf nodes and non-leaf nodes in the Btree.
> - *
> - * It is used to manage a doubly linked list of all blocks at the same
> - * level in the Btree, and to identify which type of block this is.
> - */
> -#define XFS_DA_NODE_MAGIC 0xfebe /* magic number: non-leaf blocks */
> -#define XFS_ATTR_LEAF_MAGIC 0xfbee /* magic number: attribute leaf blks */
> -#define XFS_DIR2_LEAF1_MAGIC 0xd2f1 /* magic number: v2 dirlf single blks */
> -#define XFS_DIR2_LEAFN_MAGIC 0xd2ff /* magic number: v2 dirlf multi blks */
> -
> -typedef struct xfs_da_blkinfo {
> - __be32 forw; /* previous block in list */
> - __be32 back; /* following block in list */
> - __be16 magic; /* validity check on block */
> - __be16 pad; /* unused */
> -} xfs_da_blkinfo_t;
> -
> -/*
> - * CRC enabled directory structure types
> - *
> - * The headers change size for the additional verification information, but
> - * otherwise the tree layouts and contents are unchanged. Hence the da btree
> - * code can use the struct xfs_da_blkinfo for manipulating the tree links and
> - * magic numbers without modification for both v2 and v3 nodes.
> - */
> -#define XFS_DA3_NODE_MAGIC 0x3ebe /* magic number: non-leaf blocks */
> -#define XFS_ATTR3_LEAF_MAGIC 0x3bee /* magic number: attribute leaf blks */
> -#define XFS_DIR3_LEAF1_MAGIC 0x3df1 /* magic number: v2 dirlf single blks */
> -#define XFS_DIR3_LEAFN_MAGIC 0x3dff /* magic number: v2 dirlf multi blks */
> -
> -struct xfs_da3_blkinfo {
> - /*
> - * the node link manipulation code relies on the fact that the first
> - * element of this structure is the struct xfs_da_blkinfo so it can
> - * ignore the differences in the rest of the structures.
> - */
> - struct xfs_da_blkinfo hdr;
> - __be32 crc; /* CRC of block */
> - __be64 blkno; /* first block of the buffer */
> - __be64 lsn; /* sequence number of last write */
> - uuid_t uuid; /* filesystem we belong to */
> - __be64 owner; /* inode that owns the block */
> -};
> -
> -/*
> - * This is the structure of the root and intermediate nodes in the Btree.
> - * The leaf nodes are defined above.
> - *
> - * Entries are not packed.
> - *
> - * Since we have duplicate keys, use a binary search but always follow
> - * all match in the block, not just the first match found.
> - */
> -#define XFS_DA_NODE_MAXDEPTH 5 /* max depth of Btree */
> -
> -typedef struct xfs_da_node_hdr {
> - struct xfs_da_blkinfo info; /* block type, links, etc. */
> - __be16 __count; /* count of active entries */
> - __be16 __level; /* level above leaves (leaf == 0) */
> -} xfs_da_node_hdr_t;
> -
> -struct xfs_da3_node_hdr {
> - struct xfs_da3_blkinfo info; /* block type, links, etc. */
> - __be16 __count; /* count of active entries */
> - __be16 __level; /* level above leaves (leaf == 0) */
> - __be32 __pad32;
> -};
> -
> -#define XFS_DA3_NODE_CRC_OFF (offsetof(struct xfs_da3_node_hdr, info.crc))
> -
> -typedef struct xfs_da_node_entry {
> - __be32 hashval; /* hash value for this descendant */
> - __be32 before; /* Btree block before this key */
> -} xfs_da_node_entry_t;
> -
> -typedef struct xfs_da_intnode {
> - struct xfs_da_node_hdr hdr;
> - struct xfs_da_node_entry __btree[];
> -} xfs_da_intnode_t;
> -
> -struct xfs_da3_intnode {
> - struct xfs_da3_node_hdr hdr;
> - struct xfs_da_node_entry __btree[];
> -};
> -
> -/*
> - * In-core version of the node header to abstract the differences in the v2 and
> - * v3 disk format of the headers. Callers need to convert to/from disk format as
> - * appropriate.
> - */
> -struct xfs_da3_icnode_hdr {
> - __uint32_t forw;
> - __uint32_t back;
> - __uint16_t magic;
> - __uint16_t count;
> - __uint16_t level;
> -};
> -
> -extern void xfs_da3_node_hdr_from_disk(struct xfs_da3_icnode_hdr *to,
> - struct xfs_da_intnode *from);
> -extern void xfs_da3_node_hdr_to_disk(struct xfs_da_intnode *to,
> - struct xfs_da3_icnode_hdr *from);
> -
> -static inline int
> -__xfs_da3_node_hdr_size(bool v3)
> -{
> - if (v3)
> - return sizeof(struct xfs_da3_node_hdr);
> - return sizeof(struct xfs_da_node_hdr);
> -}
> -static inline int
> -xfs_da3_node_hdr_size(struct xfs_da_intnode *dap)
> -{
> - bool v3 = dap->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC);
> -
> - return __xfs_da3_node_hdr_size(v3);
> -}
> -
> -static inline struct xfs_da_node_entry *
> -xfs_da3_node_tree_p(struct xfs_da_intnode *dap)
> -{
> - if (dap->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC)) {
> - struct xfs_da3_intnode *dap3 = (struct xfs_da3_intnode *)dap;
> - return dap3->__btree;
> - }
> - return dap->__btree;
> -}
> -
> -extern void xfs_da3_intnode_from_disk(struct xfs_da3_icnode_hdr *to,
> - struct xfs_da_intnode *from);
> -extern void xfs_da3_intnode_to_disk(struct xfs_da_intnode *to,
> - struct xfs_da3_icnode_hdr *from);
> -
> -#define XFS_LBSIZE(mp) (mp)->m_sb.sb_blocksize
> -
> -/*========================================================================
> * Btree searching and modification structure definitions.
> *========================================================================*/
>
> diff --git a/include/xfs_da_format.h b/include/xfs_da_format.h
> new file mode 100644
> index 0000000..89a1a21
> --- /dev/null
> +++ b/include/xfs_da_format.h
> @@ -0,0 +1,1362 @@
> +/*
> + * Copyright (c) 2000-2001,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
> + */
> +#ifndef __XFS_DA_FORMAT_H__
> +#define __XFS_DA_FORMAT_H__
> +
> +/*========================================================================
> + * Directory Structure when greater than XFS_LBSIZE(mp) bytes.
> + *========================================================================*/
> +
> +/*
> + * This structure is common to both leaf nodes and non-leaf nodes in the Btree.
> + *
> + * It is used to manage a doubly linked list of all blocks at the same
> + * level in the Btree, and to identify which type of block this is.
> + */
> +#define XFS_DA_NODE_MAGIC 0xfebe /* magic number: non-leaf blocks */
> +#define XFS_ATTR_LEAF_MAGIC 0xfbee /* magic number: attribute leaf blks */
> +#define XFS_DIR2_LEAF1_MAGIC 0xd2f1 /* magic number: v2 dirlf single blks */
> +#define XFS_DIR2_LEAFN_MAGIC 0xd2ff /* magic number: v2 dirlf multi blks */
> +
> +typedef struct xfs_da_blkinfo {
> + __be32 forw; /* previous block in list */
> + __be32 back; /* following block in list */
> + __be16 magic; /* validity check on block */
> + __be16 pad; /* unused */
> +} xfs_da_blkinfo_t;
> +
> +/*
> + * CRC enabled directory structure types
> + *
> + * The headers change size for the additional verification information, but
> + * otherwise the tree layouts and contents are unchanged. Hence the da btree
> + * code can use the struct xfs_da_blkinfo for manipulating the tree links and
> + * magic numbers without modification for both v2 and v3 nodes.
> + */
> +#define XFS_DA3_NODE_MAGIC 0x3ebe /* magic number: non-leaf blocks */
> +#define XFS_ATTR3_LEAF_MAGIC 0x3bee /* magic number: attribute leaf blks */
> +#define XFS_DIR3_LEAF1_MAGIC 0x3df1 /* magic number: v2 dirlf single blks */
> +#define XFS_DIR3_LEAFN_MAGIC 0x3dff /* magic number: v2 dirlf multi blks */
> +
> +struct xfs_da3_blkinfo {
> + /*
> + * the node link manipulation code relies on the fact that the first
> + * element of this structure is the struct xfs_da_blkinfo so it can
> + * ignore the differences in the rest of the structures.
> + */
> + struct xfs_da_blkinfo hdr;
> + __be32 crc; /* CRC of block */
> + __be64 blkno; /* first block of the buffer */
> + __be64 lsn; /* sequence number of last write */
> + uuid_t uuid; /* filesystem we belong to */
> + __be64 owner; /* inode that owns the block */
> +};
> +
> +/*
> + * This is the structure of the root and intermediate nodes in the Btree.
> + * The leaf nodes are defined above.
> + *
> + * Entries are not packed.
> + *
> + * Since we have duplicate keys, use a binary search but always follow
> + * all match in the block, not just the first match found.
> + */
> +#define XFS_DA_NODE_MAXDEPTH 5 /* max depth of Btree */
> +
> +typedef struct xfs_da_node_hdr {
> + struct xfs_da_blkinfo info; /* block type, links, etc. */
> + __be16 __count; /* count of active entries */
> + __be16 __level; /* level above leaves (leaf == 0) */
> +} xfs_da_node_hdr_t;
> +
> +struct xfs_da3_node_hdr {
> + struct xfs_da3_blkinfo info; /* block type, links, etc. */
> + __be16 __count; /* count of active entries */
> + __be16 __level; /* level above leaves (leaf == 0) */
> + __be32 __pad32;
> +};
> +
> +#define XFS_DA3_NODE_CRC_OFF (offsetof(struct xfs_da3_node_hdr, info.crc))
> +
> +typedef struct xfs_da_node_entry {
> + __be32 hashval; /* hash value for this descendant */
> + __be32 before; /* Btree block before this key */
> +} xfs_da_node_entry_t;
> +
> +typedef struct xfs_da_intnode {
> + struct xfs_da_node_hdr hdr;
> + struct xfs_da_node_entry __btree[];
> +} xfs_da_intnode_t;
> +
> +struct xfs_da3_intnode {
> + struct xfs_da3_node_hdr hdr;
> + struct xfs_da_node_entry __btree[];
> +};
> +
> +/*
> + * In-core version of the node header to abstract the differences in the v2 and
> + * v3 disk format of the headers. Callers need to convert to/from disk format as
> + * appropriate.
> + */
> +struct xfs_da3_icnode_hdr {
> + __uint32_t forw;
> + __uint32_t back;
> + __uint16_t magic;
> + __uint16_t count;
> + __uint16_t level;
> +};
> +
> +extern void xfs_da3_node_hdr_from_disk(struct xfs_da3_icnode_hdr *to,
> + struct xfs_da_intnode *from);
> +extern void xfs_da3_node_hdr_to_disk(struct xfs_da_intnode *to,
> + struct xfs_da3_icnode_hdr *from);
> +
> +static inline int
> +__xfs_da3_node_hdr_size(bool v3)
> +{
> + if (v3)
> + return sizeof(struct xfs_da3_node_hdr);
> + return sizeof(struct xfs_da_node_hdr);
> +}
> +static inline int
> +xfs_da3_node_hdr_size(struct xfs_da_intnode *dap)
> +{
> + bool v3 = dap->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC);
> +
> + return __xfs_da3_node_hdr_size(v3);
> +}
> +
> +static inline struct xfs_da_node_entry *
> +xfs_da3_node_tree_p(struct xfs_da_intnode *dap)
> +{
> + if (dap->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC)) {
> + struct xfs_da3_intnode *dap3 = (struct xfs_da3_intnode *)dap;
> + return dap3->__btree;
> + }
> + return dap->__btree;
> +}
> +
> +extern void xfs_da3_intnode_from_disk(struct xfs_da3_icnode_hdr *to,
> + struct xfs_da_intnode *from);
> +extern void xfs_da3_intnode_to_disk(struct xfs_da_intnode *to,
> + struct xfs_da3_icnode_hdr *from);
> +
> +#define XFS_LBSIZE(mp) (mp)->m_sb.sb_blocksize
> +
> +/*
> + * Directory version 2.
> + *
> + * There are 4 possible formats:
> + * - shortform - embedded into the inode
> + * - single block - data with embedded leaf at the end
> + * - multiple data blocks, single leaf+freeindex block
> + * - data blocks, node and leaf blocks (btree), freeindex blocks
> + *
> + * Note: many node blocks structures and constants are shared with the attr
> + * code and defined in xfs_da_btree.h.
> + */
> +
> +#define XFS_DIR2_BLOCK_MAGIC 0x58443242 /* XD2B: single block dirs */
> +#define XFS_DIR2_DATA_MAGIC 0x58443244 /* XD2D: multiblock dirs */
> +#define XFS_DIR2_FREE_MAGIC 0x58443246 /* XD2F: free index blocks */
> +
> +/*
> + * Directory Version 3 With CRCs.
> + *
> + * The tree formats are the same as for version 2 directories. The difference
> + * is in the block header and dirent formats. In many cases the v3 structures
> + * use v2 definitions as they are no different and this makes code sharing much
> + * easier.
> + *
> + * Also, the xfs_dir3_*() functions handle both v2 and v3 formats - if the
> + * format is v2 then they switch to the existing v2 code, or the format is v3
> + * they implement the v3 functionality. This means the existing dir2 is a mix of
> + * xfs_dir2/xfs_dir3 calls and functions. The xfs_dir3 functions are called
> + * where there is a difference in the formats, otherwise the code is unchanged.
> + *
> + * Where it is possible, the code decides what to do based on the magic numbers
> + * in the blocks rather than feature bits in the superblock. This means the code
> + * is as independent of the external XFS code as possible as doesn't require
> + * passing struct xfs_mount pointers into places where it isn't really
> + * necessary.
> + *
> + * Version 3 includes:
> + *
> + * - a larger block header for CRC and identification purposes and so the
> + * offsets of all the structures inside the blocks are different.
> + *
> + * - new magic numbers to be able to detect the v2/v3 types on the fly.
> + */
> +
> +#define XFS_DIR3_BLOCK_MAGIC 0x58444233 /* XDB3: single block dirs */
> +#define XFS_DIR3_DATA_MAGIC 0x58444433 /* XDD3: multiblock dirs */
> +#define XFS_DIR3_FREE_MAGIC 0x58444633 /* XDF3: free index blocks */
> +
> +/*
> + * Dirents in version 3 directories have a file type field. Additions to this
> + * list are an on-disk format change, requiring feature bits. Valid values
> + * are as follows:
> + */
> +#define XFS_DIR3_FT_UNKNOWN 0
> +#define XFS_DIR3_FT_REG_FILE 1
> +#define XFS_DIR3_FT_DIR 2
> +#define XFS_DIR3_FT_CHRDEV 3
> +#define XFS_DIR3_FT_BLKDEV 4
> +#define XFS_DIR3_FT_FIFO 5
> +#define XFS_DIR3_FT_SOCK 6
> +#define XFS_DIR3_FT_SYMLINK 7
> +#define XFS_DIR3_FT_WHT 8
> +
> +#define XFS_DIR3_FT_MAX 9
> +
> +/*
> + * Byte offset in data block and shortform entry.
> + */
> +typedef __uint16_t xfs_dir2_data_off_t;
> +#define NULLDATAOFF 0xffffU
> +typedef uint xfs_dir2_data_aoff_t; /* argument form */
> +
> +/*
> + * Normalized offset (in a data block) of the entry, really xfs_dir2_data_off_t.
> + * Only need 16 bits, this is the byte offset into the single block form.
> + */
> +typedef struct { __uint8_t i[2]; } __arch_pack xfs_dir2_sf_off_t;
> +
> +/*
> + * Offset in data space of a data entry.
> + */
> +typedef __uint32_t xfs_dir2_dataptr_t;
> +#define XFS_DIR2_MAX_DATAPTR ((xfs_dir2_dataptr_t)0xffffffff)
> +#define XFS_DIR2_NULL_DATAPTR ((xfs_dir2_dataptr_t)0)
> +
> +/*
> + * Byte offset in a directory.
> + */
> +typedef xfs_off_t xfs_dir2_off_t;
> +
> +/*
> + * Directory block number (logical dirblk in file)
> + */
> +typedef __uint32_t xfs_dir2_db_t;
> +
> +/*
> + * Inode number stored as 8 8-bit values.
> + */
> +typedef struct { __uint8_t i[8]; } xfs_dir2_ino8_t;
> +
> +/*
> + * Inode number stored as 4 8-bit values.
> + * Works a lot of the time, when all the inode numbers in a directory
> + * fit in 32 bits.
> + */
> +typedef struct { __uint8_t i[4]; } xfs_dir2_ino4_t;
> +
> +typedef union {
> + xfs_dir2_ino8_t i8;
> + xfs_dir2_ino4_t i4;
> +} xfs_dir2_inou_t;
> +#define XFS_DIR2_MAX_SHORT_INUM ((xfs_ino_t)0xffffffffULL)
> +
> +/*
> + * Directory layout when stored internal to an inode.
> + *
> + * Small directories are packed as tightly as possible so as to fit into the
> + * literal area of the inode. These "shortform" directories consist of a
> + * single xfs_dir2_sf_hdr header followed by zero or more xfs_dir2_sf_entry
> + * structures. Due the different inode number storage size and the variable
> + * length name field in the xfs_dir2_sf_entry all these structure are
> + * variable length, and the accessors in this file should be used to iterate
> + * over them.
> + */
> +typedef struct xfs_dir2_sf_hdr {
> + __uint8_t count; /* count of entries */
> + __uint8_t i8count; /* count of 8-byte inode #s */
> + xfs_dir2_inou_t parent; /* parent dir inode number */
> +} __arch_pack xfs_dir2_sf_hdr_t;
> +
> +typedef struct xfs_dir2_sf_entry {
> + __u8 namelen; /* actual name length */
> + xfs_dir2_sf_off_t offset; /* saved offset */
> + __u8 name[]; /* name, variable size */
> + /*
> + * A single byte containing the file type field follows the inode
> + * number for version 3 directory entries.
> + *
> + * A xfs_dir2_ino8_t or xfs_dir2_ino4_t follows here, at a
> + * variable offset after the name.
> + */
> +} __arch_pack xfs_dir2_sf_entry_t;
> +
> +static inline int xfs_dir2_sf_hdr_size(int i8count)
> +{
> + return sizeof(struct xfs_dir2_sf_hdr) -
> + (i8count == 0) *
> + (sizeof(xfs_dir2_ino8_t) - sizeof(xfs_dir2_ino4_t));
> +}
> +
> +static inline xfs_dir2_data_aoff_t
> +xfs_dir2_sf_get_offset(xfs_dir2_sf_entry_t *sfep)
> +{
> + return get_unaligned_be16(&sfep->offset.i);
> +}
> +
> +static inline void
> +xfs_dir2_sf_put_offset(xfs_dir2_sf_entry_t *sfep, xfs_dir2_data_aoff_t off)
> +{
> + put_unaligned_be16(off, &sfep->offset.i);
> +}
> +
> +static inline struct xfs_dir2_sf_entry *
> +xfs_dir2_sf_firstentry(struct xfs_dir2_sf_hdr *hdr)
> +{
> + return (struct xfs_dir2_sf_entry *)
> + ((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
> + * offset after the inode number. Because it's only a single byte, endian
> + * conversion is not necessary.
> + */
> +static inline __uint8_t *
> +xfs_dir3_sfe_ftypep(
> + struct xfs_dir2_sf_hdr *hdr,
> + struct xfs_dir2_sf_entry *sfep)
> +{
> + return (__uint8_t *)&sfep->name[sfep->namelen];
> +}
> +
> +static inline __uint8_t
> +xfs_dir3_sfe_get_ftype(
> + struct xfs_mount *mp,
> + struct xfs_dir2_sf_hdr *hdr,
> + struct xfs_dir2_sf_entry *sfep)
> +{
> + __uint8_t *ftp;
> +
> + if (!xfs_sb_version_hasftype(&mp->m_sb))
> + return XFS_DIR3_FT_UNKNOWN;
> +
> + ftp = xfs_dir3_sfe_ftypep(hdr, sfep);
> + if (*ftp >= XFS_DIR3_FT_MAX)
> + return XFS_DIR3_FT_UNKNOWN;
> + return *ftp;
> +}
> +
> +static inline void
> +xfs_dir3_sfe_put_ftype(
> + struct xfs_mount *mp,
> + struct xfs_dir2_sf_hdr *hdr,
> + struct xfs_dir2_sf_entry *sfep,
> + __uint8_t ftype)
> +{
> + __uint8_t *ftp;
> +
> + ASSERT(ftype < XFS_DIR3_FT_MAX);
> +
> + if (!xfs_sb_version_hasftype(&mp->m_sb))
> + return;
> + ftp = xfs_dir3_sfe_ftypep(hdr, sfep);
> + *ftp = ftype;
> +}
> +
> +/*
> + * Data block structures.
> + *
> + * A pure data block looks like the following drawing on disk:
> + *
> + * +-------------------------------------------------+
> + * | xfs_dir2_data_hdr_t |
> + * +-------------------------------------------------+
> + * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t |
> + * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t |
> + * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t |
> + * | ... |
> + * +-------------------------------------------------+
> + * | unused space |
> + * +-------------------------------------------------+
> + *
> + * As all the entries are variable size structures the accessors below should
> + * be used to iterate over them.
> + *
> + * In addition to the pure data blocks for the data and node formats,
> + * most structures are also used for the combined data/freespace "block"
> + * format below.
> + */
> +
> +#define XFS_DIR2_DATA_ALIGN_LOG 3 /* i.e., 8 bytes */
> +#define XFS_DIR2_DATA_ALIGN (1 << XFS_DIR2_DATA_ALIGN_LOG)
> +#define XFS_DIR2_DATA_FREE_TAG 0xffff
> +#define XFS_DIR2_DATA_FD_COUNT 3
> +
> +/*
> + * Directory address space divided into sections,
> + * spaces separated by 32GB.
> + */
> +#define XFS_DIR2_SPACE_SIZE (1ULL << (32 + XFS_DIR2_DATA_ALIGN_LOG))
> +#define XFS_DIR2_DATA_SPACE 0
> +#define XFS_DIR2_DATA_OFFSET (XFS_DIR2_DATA_SPACE * XFS_DIR2_SPACE_SIZE)
> +#define XFS_DIR2_DATA_FIRSTDB(mp) \
> + xfs_dir2_byte_to_db(mp, XFS_DIR2_DATA_OFFSET)
> +
> +/*
> + * Describe a free area in the data block.
> + *
> + * The freespace will be formatted as a xfs_dir2_data_unused_t.
> + */
> +typedef struct xfs_dir2_data_free {
> + __be16 offset; /* start of freespace */
> + __be16 length; /* length of freespace */
> +} xfs_dir2_data_free_t;
> +
> +/*
> + * Header for the data blocks.
> + *
> + * The code knows that XFS_DIR2_DATA_FD_COUNT is 3.
> + */
> +typedef struct xfs_dir2_data_hdr {
> + __be32 magic; /* XFS_DIR2_DATA_MAGIC or */
> + /* XFS_DIR2_BLOCK_MAGIC */
> + xfs_dir2_data_free_t bestfree[XFS_DIR2_DATA_FD_COUNT];
> +} xfs_dir2_data_hdr_t;
> +
> +/*
> + * define a structure for all the verification fields we are adding to the
> + * directory block structures. This will be used in several structures.
> + * The magic number must be the first entry to align with all the dir2
> + * structures so we determine how to decode them just by the magic number.
> + */
> +struct xfs_dir3_blk_hdr {
> + __be32 magic; /* magic number */
> + __be32 crc; /* CRC of block */
> + __be64 blkno; /* first block of the buffer */
> + __be64 lsn; /* sequence number of last write */
> + uuid_t uuid; /* filesystem we belong to */
> + __be64 owner; /* inode that owns the block */
> +};
> +
> +struct xfs_dir3_data_hdr {
> + struct xfs_dir3_blk_hdr hdr;
> + xfs_dir2_data_free_t best_free[XFS_DIR2_DATA_FD_COUNT];
> + __be32 pad; /* 64 bit alignment */
> +};
> +
> +#define XFS_DIR3_DATA_CRC_OFF offsetof(struct xfs_dir3_data_hdr, hdr.crc)
> +
> +static inline struct xfs_dir2_data_free *
> +xfs_dir3_data_bestfree_p(struct xfs_dir2_data_hdr *hdr)
> +{
> + if (hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
> + hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) {
> + struct xfs_dir3_data_hdr *hdr3 = (struct xfs_dir3_data_hdr *)hdr;
> + return hdr3->best_free;
> + }
> + return hdr->bestfree;
> +}
> +
> +/*
> + * Active entry in a data block.
> + *
> + * Aligned to 8 bytes. After the variable length name field there is a
> + * 2 byte tag field, which can be accessed using xfs_dir3_data_entry_tag_p.
> + *
> + * For dir3 structures, there is file type field between the name and the tag.
> + * This can only be manipulated by helper functions. It is packed hard against
> + * the end of the name so any padding for rounding is between the file type and
> + * the tag.
> + */
> +typedef struct xfs_dir2_data_entry {
> + __be64 inumber; /* inode number */
> + __u8 namelen; /* name length */
> + __u8 name[]; /* name bytes, no null */
> + /* __u8 filetype; */ /* type of inode we point to */
> + /* __be16 tag; */ /* starting offset of us */
> +} xfs_dir2_data_entry_t;
> +
> +/*
> + * Unused entry in a data block.
> + *
> + * Aligned to 8 bytes. Tag appears as the last 2 bytes and must be accessed
> + * using xfs_dir2_data_unused_tag_p.
> + */
> +typedef struct xfs_dir2_data_unused {
> + __be16 freetag; /* XFS_DIR2_DATA_FREE_TAG */
> + __be16 length; /* total free length */
> + /* variable offset */
> + __be16 tag; /* starting offset of us */
> +} xfs_dir2_data_unused_t;
> +
> +/*
> + * Size of a data entry.
> + */
> +static inline 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 inline int
> +xfs_dir3_data_entsize(
> + struct xfs_mount *mp,
> + int n)
> +{
> + bool ftype = xfs_sb_version_hasftype(&mp->m_sb) ? true : false;
> + return __xfs_dir3_data_entsize(ftype, n);
> +}
> +
> +static inline __uint8_t
> +xfs_dir3_dirent_get_ftype(
> + struct xfs_mount *mp,
> + struct xfs_dir2_data_entry *dep)
> +{
> + if (xfs_sb_version_hasftype(&mp->m_sb)) {
> + __uint8_t type = dep->name[dep->namelen];
> +
> + ASSERT(type < XFS_DIR3_FT_MAX);
> + if (type < XFS_DIR3_FT_MAX)
> + return type;
> +
> + }
> + return XFS_DIR3_FT_UNKNOWN;
> +}
> +
> +static inline void
> +xfs_dir3_dirent_put_ftype(
> + struct xfs_mount *mp,
> + struct xfs_dir2_data_entry *dep,
> + __uint8_t type)
> +{
> + ASSERT(type < XFS_DIR3_FT_MAX);
> + ASSERT(dep->namelen != 0);
> +
> + if (xfs_sb_version_hasftype(&mp->m_sb))
> + dep->name[dep->namelen] = type;
> +}
> +
> +/*
> + * Pointer to an entry's tag word.
> + */
> +static inline __be16 *
> +xfs_dir3_data_entry_tag_p(
> + struct xfs_mount *mp,
> + struct xfs_dir2_data_entry *dep)
> +{
> + return (__be16 *)((char *)dep +
> + xfs_dir3_data_entsize(mp, dep->namelen) - sizeof(__be16));
> +}
> +
> +/*
> + * Pointer to a freespace's tag word.
> + */
> +static inline __be16 *
> +xfs_dir2_data_unused_tag_p(struct xfs_dir2_data_unused *dup)
> +{
> + return (__be16 *)((char *)dup +
> + be16_to_cpu(dup->length) - sizeof(__be16));
> +}
> +
> +static inline size_t
> +xfs_dir3_data_hdr_size(bool dir3)
> +{
> + if (dir3)
> + return sizeof(struct xfs_dir3_data_hdr);
> + return sizeof(struct xfs_dir2_data_hdr);
> +}
> +
> +static inline size_t
> +xfs_dir3_data_entry_offset(struct xfs_dir2_data_hdr *hdr)
> +{
> + bool dir3 = hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
> + hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC);
> + return xfs_dir3_data_hdr_size(dir3);
> +}
> +
> +static inline 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(hdr));
> +}
> +
> +static inline 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(hdr));
> +}
> +
> +/*
> + * Offsets of . and .. in data space (always block 0)
> + *
> + * XXX: there is scope for significant optimisation of the logic here. Right
> + * now we are checking for "dir3 format" over and over again. Ideally we should
> + * only do it once for each operation.
> + */
> +static inline xfs_dir2_data_aoff_t
> +xfs_dir3_data_dot_offset(struct xfs_mount *mp)
> +{
> + return xfs_dir3_data_hdr_size(xfs_sb_version_hascrc(&mp->m_sb));
> +}
> +
> +static inline xfs_dir2_data_aoff_t
> +xfs_dir3_data_dotdot_offset(struct xfs_mount *mp)
> +{
> + return xfs_dir3_data_dot_offset(mp) +
> + xfs_dir3_data_entsize(mp, 1);
> +}
> +
> +static inline xfs_dir2_data_aoff_t
> +xfs_dir3_data_first_offset(struct xfs_mount *mp)
> +{
> + return xfs_dir3_data_dotdot_offset(mp) +
> + xfs_dir3_data_entsize(mp, 2);
> +}
> +
> +/*
> + * location of . and .. in data space (always block 0)
> + */
> +static inline struct xfs_dir2_data_entry *
> +xfs_dir3_data_dot_entry_p(
> + struct xfs_mount *mp,
> + struct xfs_dir2_data_hdr *hdr)
> +{
> + return (struct xfs_dir2_data_entry *)
> + ((char *)hdr + xfs_dir3_data_dot_offset(mp));
> +}
> +
> +static inline struct xfs_dir2_data_entry *
> +xfs_dir3_data_dotdot_entry_p(
> + struct xfs_mount *mp,
> + struct xfs_dir2_data_hdr *hdr)
> +{
> + return (struct xfs_dir2_data_entry *)
> + ((char *)hdr + xfs_dir3_data_dotdot_offset(mp));
> +}
> +
> +static inline struct xfs_dir2_data_entry *
> +xfs_dir3_data_first_entry_p(
> + struct xfs_mount *mp,
> + struct xfs_dir2_data_hdr *hdr)
> +{
> + return (struct xfs_dir2_data_entry *)
> + ((char *)hdr + xfs_dir3_data_first_offset(mp));
> +}
> +
> +/*
> + * Leaf block structures.
> + *
> + * A pure leaf block looks like the following drawing on disk:
> + *
> + * +---------------------------+
> + * | xfs_dir2_leaf_hdr_t |
> + * +---------------------------+
> + * | xfs_dir2_leaf_entry_t |
> + * | xfs_dir2_leaf_entry_t |
> + * | xfs_dir2_leaf_entry_t |
> + * | xfs_dir2_leaf_entry_t |
> + * | ... |
> + * +---------------------------+
> + * | xfs_dir2_data_off_t |
> + * | xfs_dir2_data_off_t |
> + * | xfs_dir2_data_off_t |
> + * | ... |
> + * +---------------------------+
> + * | xfs_dir2_leaf_tail_t |
> + * +---------------------------+
> + *
> + * The xfs_dir2_data_off_t members (bests) and tail are at the end of the block
> + * for single-leaf (magic = XFS_DIR2_LEAF1_MAGIC) blocks only, but not present
> + * for directories with separate leaf nodes and free space blocks
> + * (magic = XFS_DIR2_LEAFN_MAGIC).
> + *
> + * As all the entries are variable size structures the accessors below should
> + * be used to iterate over them.
> + */
> +
> +/*
> + * Offset of the leaf/node space. First block in this space
> + * is the btree root.
> + */
> +#define XFS_DIR2_LEAF_SPACE 1
> +#define XFS_DIR2_LEAF_OFFSET (XFS_DIR2_LEAF_SPACE * XFS_DIR2_SPACE_SIZE)
> +#define XFS_DIR2_LEAF_FIRSTDB(mp) \
> + xfs_dir2_byte_to_db(mp, XFS_DIR2_LEAF_OFFSET)
> +
> +/*
> + * Leaf block header.
> + */
> +typedef struct xfs_dir2_leaf_hdr {
> + xfs_da_blkinfo_t info; /* header for da routines */
> + __be16 count; /* count of entries */
> + __be16 stale; /* count of stale entries */
> +} xfs_dir2_leaf_hdr_t;
> +
> +struct xfs_dir3_leaf_hdr {
> + struct xfs_da3_blkinfo info; /* header for da routines */
> + __be16 count; /* count of entries */
> + __be16 stale; /* count of stale entries */
> + __be32 pad; /* 64 bit alignment */
> +};
> +
> +struct xfs_dir3_icleaf_hdr {
> + __uint32_t forw;
> + __uint32_t back;
> + __uint16_t magic;
> + __uint16_t count;
> + __uint16_t stale;
> +};
> +
> +/*
> + * Leaf block entry.
> + */
> +typedef struct xfs_dir2_leaf_entry {
> + __be32 hashval; /* hash value of name */
> + __be32 address; /* address of data entry */
> +} xfs_dir2_leaf_entry_t;
> +
> +/*
> + * Leaf block tail.
> + */
> +typedef struct xfs_dir2_leaf_tail {
> + __be32 bestcount;
> +} xfs_dir2_leaf_tail_t;
> +
> +/*
> + * Leaf block.
> + */
> +typedef struct xfs_dir2_leaf {
> + xfs_dir2_leaf_hdr_t hdr; /* leaf header */
> + xfs_dir2_leaf_entry_t __ents[]; /* entries */
> +} xfs_dir2_leaf_t;
> +
> +struct xfs_dir3_leaf {
> + struct xfs_dir3_leaf_hdr hdr; /* leaf header */
> + struct xfs_dir2_leaf_entry __ents[]; /* entries */
> +};
> +
> +#define XFS_DIR3_LEAF_CRC_OFF offsetof(struct xfs_dir3_leaf_hdr, info.crc)
> +
> +extern void xfs_dir3_leaf_hdr_from_disk(struct xfs_dir3_icleaf_hdr *to,
> + struct xfs_dir2_leaf *from);
> +
> +static inline int
> +xfs_dir3_leaf_hdr_size(struct xfs_dir2_leaf *lp)
> +{
> + if (lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) ||
> + lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC))
> + return sizeof(struct xfs_dir3_leaf_hdr);
> + return sizeof(struct xfs_dir2_leaf_hdr);
> +}
> +
> +static inline int
> +xfs_dir3_max_leaf_ents(struct xfs_mount *mp, struct xfs_dir2_leaf *lp)
> +{
> + return (mp->m_dirblksize - xfs_dir3_leaf_hdr_size(lp)) /
> + (uint)sizeof(struct xfs_dir2_leaf_entry);
> +}
> +
> +/*
> + * Get address of the bestcount field in the single-leaf block.
> + */
> +static inline struct xfs_dir2_leaf_entry *
> +xfs_dir3_leaf_ents_p(struct xfs_dir2_leaf *lp)
> +{
> + if (lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) ||
> + lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)) {
> + struct xfs_dir3_leaf *lp3 = (struct xfs_dir3_leaf *)lp;
> + return lp3->__ents;
> + }
> + return lp->__ents;
> +}
> +
> +/*
> + * Get address of the bestcount field in the single-leaf block.
> + */
> +static inline struct xfs_dir2_leaf_tail *
> +xfs_dir2_leaf_tail_p(struct xfs_mount *mp, struct xfs_dir2_leaf *lp)
> +{
> + return (struct xfs_dir2_leaf_tail *)
> + ((char *)lp + mp->m_dirblksize -
> + sizeof(struct xfs_dir2_leaf_tail));
> +}
> +
> +/*
> + * Get address of the bests array in the single-leaf block.
> + */
> +static inline __be16 *
> +xfs_dir2_leaf_bests_p(struct xfs_dir2_leaf_tail *ltp)
> +{
> + return (__be16 *)ltp - be32_to_cpu(ltp->bestcount);
> +}
> +
> +/*
> + * DB blocks here are logical directory block numbers, not filesystem blocks.
> + */
> +
> +/*
> + * Convert dataptr to byte in file space
> + */
> +static inline xfs_dir2_off_t
> +xfs_dir2_dataptr_to_byte(struct xfs_mount *mp, xfs_dir2_dataptr_t dp)
> +{
> + return (xfs_dir2_off_t)dp << XFS_DIR2_DATA_ALIGN_LOG;
> +}
> +
> +/*
> + * Convert byte in file space to dataptr. It had better be aligned.
> + */
> +static inline xfs_dir2_dataptr_t
> +xfs_dir2_byte_to_dataptr(struct xfs_mount *mp, xfs_dir2_off_t by)
> +{
> + return (xfs_dir2_dataptr_t)(by >> XFS_DIR2_DATA_ALIGN_LOG);
> +}
> +
> +/*
> + * Convert byte in space to (DB) block
> + */
> +static inline xfs_dir2_db_t
> +xfs_dir2_byte_to_db(struct xfs_mount *mp, xfs_dir2_off_t by)
> +{
> + return (xfs_dir2_db_t)
> + (by >> (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog));
> +}
> +
> +/*
> + * Convert dataptr to a block number
> + */
> +static inline xfs_dir2_db_t
> +xfs_dir2_dataptr_to_db(struct xfs_mount *mp, xfs_dir2_dataptr_t dp)
> +{
> + return xfs_dir2_byte_to_db(mp, xfs_dir2_dataptr_to_byte(mp, dp));
> +}
> +
> +/*
> + * Convert byte in space to offset in a block
> + */
> +static inline xfs_dir2_data_aoff_t
> +xfs_dir2_byte_to_off(struct xfs_mount *mp, xfs_dir2_off_t by)
> +{
> + return (xfs_dir2_data_aoff_t)(by &
> + ((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) - 1));
> +}
> +
> +/*
> + * Convert dataptr to a byte offset in a block
> + */
> +static inline xfs_dir2_data_aoff_t
> +xfs_dir2_dataptr_to_off(struct xfs_mount *mp, xfs_dir2_dataptr_t dp)
> +{
> + return xfs_dir2_byte_to_off(mp, xfs_dir2_dataptr_to_byte(mp, dp));
> +}
> +
> +/*
> + * Convert block and offset to byte in space
> + */
> +static inline xfs_dir2_off_t
> +xfs_dir2_db_off_to_byte(struct xfs_mount *mp, xfs_dir2_db_t db,
> + xfs_dir2_data_aoff_t o)
> +{
> + return ((xfs_dir2_off_t)db <<
> + (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) + o;
> +}
> +
> +/*
> + * Convert block (DB) to block (dablk)
> + */
> +static inline xfs_dablk_t
> +xfs_dir2_db_to_da(struct xfs_mount *mp, xfs_dir2_db_t db)
> +{
> + return (xfs_dablk_t)(db << mp->m_sb.sb_dirblklog);
> +}
> +
> +/*
> + * Convert byte in space to (DA) block
> + */
> +static inline xfs_dablk_t
> +xfs_dir2_byte_to_da(struct xfs_mount *mp, xfs_dir2_off_t by)
> +{
> + return xfs_dir2_db_to_da(mp, xfs_dir2_byte_to_db(mp, by));
> +}
> +
> +/*
> + * Convert block and offset to dataptr
> + */
> +static inline xfs_dir2_dataptr_t
> +xfs_dir2_db_off_to_dataptr(struct xfs_mount *mp, xfs_dir2_db_t db,
> + xfs_dir2_data_aoff_t o)
> +{
> + return xfs_dir2_byte_to_dataptr(mp, xfs_dir2_db_off_to_byte(mp, db, o));
> +}
> +
> +/*
> + * Convert block (dablk) to block (DB)
> + */
> +static inline xfs_dir2_db_t
> +xfs_dir2_da_to_db(struct xfs_mount *mp, xfs_dablk_t da)
> +{
> + return (xfs_dir2_db_t)(da >> mp->m_sb.sb_dirblklog);
> +}
> +
> +/*
> + * Convert block (dablk) to byte offset in space
> + */
> +static inline xfs_dir2_off_t
> +xfs_dir2_da_to_byte(struct xfs_mount *mp, xfs_dablk_t da)
> +{
> + return xfs_dir2_db_off_to_byte(mp, xfs_dir2_da_to_db(mp, da), 0);
> +}
> +
> +/*
> + * Free space block defintions for the node format.
> + */
> +
> +/*
> + * Offset of the freespace index.
> + */
> +#define XFS_DIR2_FREE_SPACE 2
> +#define XFS_DIR2_FREE_OFFSET (XFS_DIR2_FREE_SPACE * XFS_DIR2_SPACE_SIZE)
> +#define XFS_DIR2_FREE_FIRSTDB(mp) \
> + xfs_dir2_byte_to_db(mp, XFS_DIR2_FREE_OFFSET)
> +
> +typedef struct xfs_dir2_free_hdr {
> + __be32 magic; /* XFS_DIR2_FREE_MAGIC */
> + __be32 firstdb; /* db of first entry */
> + __be32 nvalid; /* count of valid entries */
> + __be32 nused; /* count of used entries */
> +} xfs_dir2_free_hdr_t;
> +
> +typedef struct xfs_dir2_free {
> + xfs_dir2_free_hdr_t hdr; /* block header */
> + __be16 bests[]; /* best free counts */
> + /* unused entries are -1 */
> +} xfs_dir2_free_t;
> +
> +struct xfs_dir3_free_hdr {
> + struct xfs_dir3_blk_hdr hdr;
> + __be32 firstdb; /* db of first entry */
> + __be32 nvalid; /* count of valid entries */
> + __be32 nused; /* count of used entries */
> + __be32 pad; /* 64 bit alignment */
> +};
> +
> +struct xfs_dir3_free {
> + struct xfs_dir3_free_hdr hdr;
> + __be16 bests[]; /* best free counts */
> + /* unused entries are -1 */
> +};
> +
> +#define XFS_DIR3_FREE_CRC_OFF offsetof(struct xfs_dir3_free, hdr.hdr.crc)
> +
> +/*
> + * In core version of the free block header, abstracted away from on-disk format
> + * differences. Use this in the code, and convert to/from the disk version using
> + * xfs_dir3_free_hdr_from_disk/xfs_dir3_free_hdr_to_disk.
> + */
> +struct xfs_dir3_icfree_hdr {
> + __uint32_t magic;
> + __uint32_t firstdb;
> + __uint32_t nvalid;
> + __uint32_t nused;
> +
> +};
> +
> +void xfs_dir3_free_hdr_from_disk(struct xfs_dir3_icfree_hdr *to,
> + struct xfs_dir2_free *from);
> +
> +static inline int
> +xfs_dir3_free_hdr_size(struct xfs_mount *mp)
> +{
> + if (xfs_sb_version_hascrc(&mp->m_sb))
> + return sizeof(struct xfs_dir3_free_hdr);
> + return sizeof(struct xfs_dir2_free_hdr);
> +}
> +
> +static inline int
> +xfs_dir3_free_max_bests(struct xfs_mount *mp)
> +{
> + return (mp->m_dirblksize - xfs_dir3_free_hdr_size(mp)) /
> + sizeof(xfs_dir2_data_off_t);
> +}
> +
> +static inline __be16 *
> +xfs_dir3_free_bests_p(struct xfs_mount *mp, struct xfs_dir2_free *free)
> +{
> + return (__be16 *)((char *)free + xfs_dir3_free_hdr_size(mp));
> +}
> +
> +/*
> + * Convert data space db to the corresponding free db.
> + */
> +static inline xfs_dir2_db_t
> +xfs_dir2_db_to_fdb(struct xfs_mount *mp, xfs_dir2_db_t db)
> +{
> + return XFS_DIR2_FREE_FIRSTDB(mp) + db / xfs_dir3_free_max_bests(mp);
> +}
> +
> +/*
> + * Convert data space db to the corresponding index in a free db.
> + */
> +static inline int
> +xfs_dir2_db_to_fdindex(struct xfs_mount *mp, xfs_dir2_db_t db)
> +{
> + return db % xfs_dir3_free_max_bests(mp);
> +}
> +
> +/*
> + * Single block format.
> + *
> + * The single block format looks like the following drawing on disk:
> + *
> + * +-------------------------------------------------+
> + * | xfs_dir2_data_hdr_t |
> + * +-------------------------------------------------+
> + * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t |
> + * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t |
> + * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t :
> + * | ... |
> + * +-------------------------------------------------+
> + * | unused space |
> + * +-------------------------------------------------+
> + * | ... |
> + * | xfs_dir2_leaf_entry_t |
> + * | xfs_dir2_leaf_entry_t |
> + * +-------------------------------------------------+
> + * | xfs_dir2_block_tail_t |
> + * +-------------------------------------------------+
> + *
> + * As all the entries are variable size structures the accessors below should
> + * be used to iterate over them.
> + */
> +
> +typedef struct xfs_dir2_block_tail {
> + __be32 count; /* count of leaf entries */
> + __be32 stale; /* count of stale lf entries */
> +} xfs_dir2_block_tail_t;
> +
> +/*
> + * Pointer to the leaf header embedded in a data block (1-block format)
> + */
> +static inline struct xfs_dir2_block_tail *
> +xfs_dir2_block_tail_p(struct xfs_mount *mp, struct xfs_dir2_data_hdr *hdr)
> +{
> + return ((struct xfs_dir2_block_tail *)
> + ((char *)hdr + mp->m_dirblksize)) - 1;
> +}
> +
> +/*
> + * Pointer to the leaf entries embedded in a data block (1-block format)
> + */
> +static inline struct xfs_dir2_leaf_entry *
> +xfs_dir2_block_leaf_p(struct xfs_dir2_block_tail *btp)
> +{
> + return ((struct xfs_dir2_leaf_entry *)btp) - be32_to_cpu(btp->count);
> +}
> +
> +
> +/*
> + * Attribute storage layout
> + *
> + * Attribute lists are structured around Btrees where all the data
> + * elements are in the leaf nodes. Attribute names are hashed into an int,
> + * then that int is used as the index into the Btree. Since the hashval
> + * of an attribute name may not be unique, we may have duplicate keys. The
> + * internal links in the Btree are logical block offsets into the file.
> + *
> + *========================================================================
> + * Attribute structure when equal to XFS_LBSIZE(mp) bytes.
> + *========================================================================
> + *
> + * Struct leaf_entry's are packed from the top. Name/values grow from the
> + * bottom but are not packed. The freemap contains run-length-encoded entries
> + * for the free bytes after the leaf_entry's, but only the N largest such,
> + * smaller runs are dropped. When the freemap doesn't show enough space
> + * for an allocation, we compact the name/value area and try again. If we
> + * still don't have enough space, then we have to split the block. The
> + * name/value structs (both local and remote versions) must be 32bit aligned.
> + *
> + * Since we have duplicate hash keys, for each key that matches, compare
> + * the actual name string. The root and intermediate node search always
> + * takes the first-in-the-block key match found, so we should only have
> + * to work "forw"ard. If none matches, continue with the "forw"ard leaf
> + * nodes until the hash key changes or the attribute name is found.
> + *
> + * We store the fact that an attribute is a ROOT/USER/SECURE attribute in
> + * the leaf_entry. The namespaces are independent only because we also look
> + * at the namespace bit when we are looking for a matching attribute name.
> + *
> + * We also store an "incomplete" bit in the leaf_entry. It shows that an
> + * attribute is in the middle of being created and should not be shown to
> + * the user if we crash during the time that the bit is set. We clear the
> + * bit when we have finished setting up the attribute. We do this because
> + * we cannot create some large attributes inside a single transaction, and we
> + * need some indication that we weren't finished if we crash in the middle.
> + */
> +#define XFS_ATTR_LEAF_MAPSIZE 3 /* how many freespace slots */
> +
> +typedef struct xfs_attr_leaf_map { /* RLE map of free bytes */
> + __be16 base; /* base of free region */
> + __be16 size; /* length of free region */
> +} xfs_attr_leaf_map_t;
> +
> +typedef struct xfs_attr_leaf_hdr { /* constant-structure header block */
> + xfs_da_blkinfo_t info; /* block type, links, etc. */
> + __be16 count; /* count of active leaf_entry's */
> + __be16 usedbytes; /* num bytes of names/values stored */
> + __be16 firstused; /* first used byte in name area */
> + __u8 holes; /* != 0 if blk needs compaction */
> + __u8 pad1;
> + xfs_attr_leaf_map_t freemap[XFS_ATTR_LEAF_MAPSIZE];
> + /* N largest free regions */
> +} xfs_attr_leaf_hdr_t;
> +
> +typedef struct xfs_attr_leaf_entry { /* sorted on key, not name */
> + __be32 hashval; /* hash value of name */
> + __be16 nameidx; /* index into buffer of name/value */
> + __u8 flags; /* LOCAL/ROOT/SECURE/INCOMPLETE flag */
> + __u8 pad2; /* unused pad byte */
> +} xfs_attr_leaf_entry_t;
> +
> +typedef struct xfs_attr_leaf_name_local {
> + __be16 valuelen; /* number of bytes in value */
> + __u8 namelen; /* length of name bytes */
> + __u8 nameval[1]; /* name/value bytes */
> +} xfs_attr_leaf_name_local_t;
> +
> +typedef struct xfs_attr_leaf_name_remote {
> + __be32 valueblk; /* block number of value bytes */
> + __be32 valuelen; /* number of bytes in value */
> + __u8 namelen; /* length of name bytes */
> + __u8 name[1]; /* name bytes */
> +} xfs_attr_leaf_name_remote_t;
> +
> +typedef struct xfs_attr_leafblock {
> + xfs_attr_leaf_hdr_t hdr; /* constant-structure header block */
> + xfs_attr_leaf_entry_t entries[1]; /* sorted on key, not name */
> + xfs_attr_leaf_name_local_t namelist; /* grows from bottom of buf */
> + xfs_attr_leaf_name_remote_t valuelist; /* grows from bottom of buf */
> +} xfs_attr_leafblock_t;
> +
> +/*
> + * CRC enabled leaf structures. Called "version 3" structures to match the
> + * version number of the directory and dablk structures for this feature, and
> + * attr2 is already taken by the variable inode attribute fork size feature.
> + */
> +struct xfs_attr3_leaf_hdr {
> + struct xfs_da3_blkinfo info;
> + __be16 count;
> + __be16 usedbytes;
> + __be16 firstused;
> + __u8 holes;
> + __u8 pad1;
> + struct xfs_attr_leaf_map freemap[XFS_ATTR_LEAF_MAPSIZE];
> + __be32 pad2; /* 64 bit alignment */
> +};
> +
> +#define XFS_ATTR3_LEAF_CRC_OFF (offsetof(struct xfs_attr3_leaf_hdr, info.crc))
> +
> +struct xfs_attr3_leafblock {
> + struct xfs_attr3_leaf_hdr hdr;
> + struct xfs_attr_leaf_entry entries[1];
> +
> + /*
> + * The rest of the block contains the following structures after the
> + * leaf entries, growing from the bottom up. The variables are never
> + * referenced, the locations accessed purely from helper functions.
> + *
> + * struct xfs_attr_leaf_name_local
> + * struct xfs_attr_leaf_name_remote
> + */
> +};
> +
> +/*
> + * incore, neutral version of the attribute leaf header
> + */
> +struct xfs_attr3_icleaf_hdr {
> + __uint32_t forw;
> + __uint32_t back;
> + __uint16_t magic;
> + __uint16_t count;
> + __uint16_t usedbytes;
> + __uint16_t firstused;
> + __u8 holes;
> + struct {
> + __uint16_t base;
> + __uint16_t size;
> + } freemap[XFS_ATTR_LEAF_MAPSIZE];
> +};
> +
> +/*
> + * Flags used in the leaf_entry[i].flags field.
> + * NOTE: the INCOMPLETE bit must not collide with the flags bits specified
> + * on the system call, they are "or"ed together for various operations.
> + */
> +#define XFS_ATTR_LOCAL_BIT 0 /* attr is stored locally */
> +#define XFS_ATTR_ROOT_BIT 1 /* limit access to trusted attrs */
> +#define XFS_ATTR_SECURE_BIT 2 /* limit access to secure attrs */
> +#define XFS_ATTR_INCOMPLETE_BIT 7 /* attr in middle of create/delete */
> +#define XFS_ATTR_LOCAL (1 << XFS_ATTR_LOCAL_BIT)
> +#define XFS_ATTR_ROOT (1 << XFS_ATTR_ROOT_BIT)
> +#define XFS_ATTR_SECURE (1 << XFS_ATTR_SECURE_BIT)
> +#define XFS_ATTR_INCOMPLETE (1 << XFS_ATTR_INCOMPLETE_BIT)
> +
> +/*
> + * Conversion macros for converting namespace bits from argument flags
> + * to ondisk flags.
> + */
> +#define XFS_ATTR_NSP_ARGS_MASK (ATTR_ROOT | ATTR_SECURE)
> +#define XFS_ATTR_NSP_ONDISK_MASK (XFS_ATTR_ROOT | XFS_ATTR_SECURE)
> +#define XFS_ATTR_NSP_ONDISK(flags) ((flags) & XFS_ATTR_NSP_ONDISK_MASK)
> +#define XFS_ATTR_NSP_ARGS(flags) ((flags) & XFS_ATTR_NSP_ARGS_MASK)
> +#define XFS_ATTR_NSP_ARGS_TO_ONDISK(x) (((x) & ATTR_ROOT ? XFS_ATTR_ROOT : 0) |\
> + ((x) & ATTR_SECURE ? XFS_ATTR_SECURE : 0))
> +#define XFS_ATTR_NSP_ONDISK_TO_ARGS(x) (((x) & XFS_ATTR_ROOT ? ATTR_ROOT : 0) |\
> + ((x) & XFS_ATTR_SECURE ? ATTR_SECURE : 0))
> +
> +/*
> + * Alignment for namelist and valuelist entries (since they are mixed
> + * there can be only one alignment value)
> + */
> +#define XFS_ATTR_LEAF_NAME_ALIGN ((uint)sizeof(xfs_dablk_t))
> +
> +static inline int
> +xfs_attr3_leaf_hdr_size(struct xfs_attr_leafblock *leafp)
> +{
> + if (leafp->hdr.info.magic == cpu_to_be16(XFS_ATTR3_LEAF_MAGIC))
> + return sizeof(struct xfs_attr3_leaf_hdr);
> + return sizeof(struct xfs_attr_leaf_hdr);
> +}
> +
> +static inline struct xfs_attr_leaf_entry *
> +xfs_attr3_leaf_entryp(xfs_attr_leafblock_t *leafp)
> +{
> + if (leafp->hdr.info.magic == cpu_to_be16(XFS_ATTR3_LEAF_MAGIC))
> + return &((struct xfs_attr3_leafblock *)leafp)->entries[0];
> + return &leafp->entries[0];
> +}
> +
> +/*
> + * Cast typed pointers for "local" and "remote" name/value structs.
> + */
> +static inline char *
> +xfs_attr3_leaf_name(xfs_attr_leafblock_t *leafp, int idx)
> +{
> + struct xfs_attr_leaf_entry *entries = xfs_attr3_leaf_entryp(leafp);
> +
> + return &((char *)leafp)[be16_to_cpu(entries[idx].nameidx)];
> +}
> +
> +static inline xfs_attr_leaf_name_remote_t *
> +xfs_attr3_leaf_name_remote(xfs_attr_leafblock_t *leafp, int idx)
> +{
> + return (xfs_attr_leaf_name_remote_t *)xfs_attr3_leaf_name(leafp, idx);
> +}
> +
> +static inline xfs_attr_leaf_name_local_t *
> +xfs_attr3_leaf_name_local(xfs_attr_leafblock_t *leafp, int idx)
> +{
> + return (xfs_attr_leaf_name_local_t *)xfs_attr3_leaf_name(leafp, idx);
> +}
> +
> +/*
> + * Calculate total bytes used (including trailing pad for alignment) for
> + * a "local" name/value structure, a "remote" name/value structure, and
> + * a pointer which might be either.
> + */
> +static inline int xfs_attr_leaf_entsize_remote(int nlen)
> +{
> + return ((uint)sizeof(xfs_attr_leaf_name_remote_t) - 1 + (nlen) + \
> + XFS_ATTR_LEAF_NAME_ALIGN - 1) & ~(XFS_ATTR_LEAF_NAME_ALIGN - 1);
> +}
> +
> +static inline int xfs_attr_leaf_entsize_local(int nlen, int vlen)
> +{
> + return ((uint)sizeof(xfs_attr_leaf_name_local_t) - 1 + (nlen) + (vlen) +
> + XFS_ATTR_LEAF_NAME_ALIGN - 1) & ~(XFS_ATTR_LEAF_NAME_ALIGN - 1);
> +}
> +
> +static inline int xfs_attr_leaf_entsize_local_max(int bsize)
> +{
> + return (((bsize) >> 1) + ((bsize) >> 2));
> +}
> +
> +
> +
> +/*
> + * Remote attribute block format definition
> + *
> + * There is one of these headers per filesystem block in a remote attribute.
> + * This is done to ensure there is a 1:1 mapping between the attribute value
> + * length and the number of blocks needed to store the attribute. This makes the
> + * verification of a buffer a little more complex, but greatly simplifies the
> + * allocation, reading and writing of these attributes as we don't have to guess
> + * the number of blocks needed to store the attribute data.
> + */
> +#define XFS_ATTR3_RMT_MAGIC 0x5841524d /* XARM */
> +
> +struct xfs_attr3_rmt_hdr {
> + __be32 rm_magic;
> + __be32 rm_offset;
> + __be32 rm_bytes;
> + __be32 rm_crc;
> + uuid_t rm_uuid;
> + __be64 rm_owner;
> + __be64 rm_blkno;
> + __be64 rm_lsn;
> +};
> +
> +#define XFS_ATTR3_RMT_CRC_OFF offsetof(struct xfs_attr3_rmt_hdr, rm_crc)
> +
> +#define XFS_ATTR3_RMT_BUF_SPACE(mp, bufsize) \
> + ((bufsize) - (xfs_sb_version_hascrc(&(mp)->m_sb) ? \
> + sizeof(struct xfs_attr3_rmt_hdr) : 0))
> +
> +#endif /* __XFS_DA_FORMAT_H__ */
> diff --git a/include/xfs_dir2_format.h b/include/xfs_dir2_format.h
> deleted file mode 100644
> index 9cf6738..0000000
> --- a/include/xfs_dir2_format.h
> +++ /dev/null
> @@ -1,964 +0,0 @@
> -/*
> - * Copyright (c) 2000-2001,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
> - */
> -#ifndef __XFS_DIR2_FORMAT_H__
> -#define __XFS_DIR2_FORMAT_H__
> -
> -/*
> - * Directory version 2.
> - *
> - * There are 4 possible formats:
> - * - shortform - embedded into the inode
> - * - single block - data with embedded leaf at the end
> - * - multiple data blocks, single leaf+freeindex block
> - * - data blocks, node and leaf blocks (btree), freeindex blocks
> - *
> - * Note: many node blocks structures and constants are shared with the attr
> - * code and defined in xfs_da_btree.h.
> - */
> -
> -#define XFS_DIR2_BLOCK_MAGIC 0x58443242 /* XD2B: single block dirs */
> -#define XFS_DIR2_DATA_MAGIC 0x58443244 /* XD2D: multiblock dirs */
> -#define XFS_DIR2_FREE_MAGIC 0x58443246 /* XD2F: free index blocks */
> -
> -/*
> - * Directory Version 3 With CRCs.
> - *
> - * The tree formats are the same as for version 2 directories. The difference
> - * is in the block header and dirent formats. In many cases the v3 structures
> - * use v2 definitions as they are no different and this makes code sharing much
> - * easier.
> - *
> - * Also, the xfs_dir3_*() functions handle both v2 and v3 formats - if the
> - * format is v2 then they switch to the existing v2 code, or the format is v3
> - * they implement the v3 functionality. This means the existing dir2 is a mix of
> - * xfs_dir2/xfs_dir3 calls and functions. The xfs_dir3 functions are called
> - * where there is a difference in the formats, otherwise the code is unchanged.
> - *
> - * Where it is possible, the code decides what to do based on the magic numbers
> - * in the blocks rather than feature bits in the superblock. This means the code
> - * is as independent of the external XFS code as possible as doesn't require
> - * passing struct xfs_mount pointers into places where it isn't really
> - * necessary.
> - *
> - * Version 3 includes:
> - *
> - * - a larger block header for CRC and identification purposes and so the
> - * offsets of all the structures inside the blocks are different.
> - *
> - * - new magic numbers to be able to detect the v2/v3 types on the fly.
> - */
> -
> -#define XFS_DIR3_BLOCK_MAGIC 0x58444233 /* XDB3: single block dirs */
> -#define XFS_DIR3_DATA_MAGIC 0x58444433 /* XDD3: multiblock dirs */
> -#define XFS_DIR3_FREE_MAGIC 0x58444633 /* XDF3: free index blocks */
> -
> -/*
> - * Dirents in version 3 directories have a file type field. Additions to this
> - * list are an on-disk format change, requiring feature bits. Valid values
> - * are as follows:
> - */
> -#define XFS_DIR3_FT_UNKNOWN 0
> -#define XFS_DIR3_FT_REG_FILE 1
> -#define XFS_DIR3_FT_DIR 2
> -#define XFS_DIR3_FT_CHRDEV 3
> -#define XFS_DIR3_FT_BLKDEV 4
> -#define XFS_DIR3_FT_FIFO 5
> -#define XFS_DIR3_FT_SOCK 6
> -#define XFS_DIR3_FT_SYMLINK 7
> -#define XFS_DIR3_FT_WHT 8
> -
> -#define XFS_DIR3_FT_MAX 9
> -
> -/*
> - * Byte offset in data block and shortform entry.
> - */
> -typedef __uint16_t xfs_dir2_data_off_t;
> -#define NULLDATAOFF 0xffffU
> -typedef uint xfs_dir2_data_aoff_t; /* argument form */
> -
> -/*
> - * Normalized offset (in a data block) of the entry, really xfs_dir2_data_off_t.
> - * Only need 16 bits, this is the byte offset into the single block form.
> - */
> -typedef struct { __uint8_t i[2]; } __arch_pack xfs_dir2_sf_off_t;
> -
> -/*
> - * Offset in data space of a data entry.
> - */
> -typedef __uint32_t xfs_dir2_dataptr_t;
> -#define XFS_DIR2_MAX_DATAPTR ((xfs_dir2_dataptr_t)0xffffffff)
> -#define XFS_DIR2_NULL_DATAPTR ((xfs_dir2_dataptr_t)0)
> -
> -/*
> - * Byte offset in a directory.
> - */
> -typedef xfs_off_t xfs_dir2_off_t;
> -
> -/*
> - * Directory block number (logical dirblk in file)
> - */
> -typedef __uint32_t xfs_dir2_db_t;
> -
> -/*
> - * Inode number stored as 8 8-bit values.
> - */
> -typedef struct { __uint8_t i[8]; } xfs_dir2_ino8_t;
> -
> -/*
> - * Inode number stored as 4 8-bit values.
> - * Works a lot of the time, when all the inode numbers in a directory
> - * fit in 32 bits.
> - */
> -typedef struct { __uint8_t i[4]; } xfs_dir2_ino4_t;
> -
> -typedef union {
> - xfs_dir2_ino8_t i8;
> - xfs_dir2_ino4_t i4;
> -} xfs_dir2_inou_t;
> -#define XFS_DIR2_MAX_SHORT_INUM ((xfs_ino_t)0xffffffffULL)
> -
> -/*
> - * Directory layout when stored internal to an inode.
> - *
> - * Small directories are packed as tightly as possible so as to fit into the
> - * literal area of the inode. These "shortform" directories consist of a
> - * single xfs_dir2_sf_hdr header followed by zero or more xfs_dir2_sf_entry
> - * structures. Due the different inode number storage size and the variable
> - * length name field in the xfs_dir2_sf_entry all these structure are
> - * variable length, and the accessors in this file should be used to iterate
> - * over them.
> - */
> -typedef struct xfs_dir2_sf_hdr {
> - __uint8_t count; /* count of entries */
> - __uint8_t i8count; /* count of 8-byte inode #s */
> - xfs_dir2_inou_t parent; /* parent dir inode number */
> -} __arch_pack xfs_dir2_sf_hdr_t;
> -
> -typedef struct xfs_dir2_sf_entry {
> - __u8 namelen; /* actual name length */
> - xfs_dir2_sf_off_t offset; /* saved offset */
> - __u8 name[]; /* name, variable size */
> - /*
> - * A single byte containing the file type field follows the inode
> - * number for version 3 directory entries.
> - *
> - * A xfs_dir2_ino8_t or xfs_dir2_ino4_t follows here, at a
> - * variable offset after the name.
> - */
> -} __arch_pack xfs_dir2_sf_entry_t;
> -
> -static inline int xfs_dir2_sf_hdr_size(int i8count)
> -{
> - return sizeof(struct xfs_dir2_sf_hdr) -
> - (i8count == 0) *
> - (sizeof(xfs_dir2_ino8_t) - sizeof(xfs_dir2_ino4_t));
> -}
> -
> -static inline xfs_dir2_data_aoff_t
> -xfs_dir2_sf_get_offset(xfs_dir2_sf_entry_t *sfep)
> -{
> - return get_unaligned_be16(&sfep->offset.i);
> -}
> -
> -static inline void
> -xfs_dir2_sf_put_offset(xfs_dir2_sf_entry_t *sfep, xfs_dir2_data_aoff_t off)
> -{
> - put_unaligned_be16(off, &sfep->offset.i);
> -}
> -
> -static inline struct xfs_dir2_sf_entry *
> -xfs_dir2_sf_firstentry(struct xfs_dir2_sf_hdr *hdr)
> -{
> - return (struct xfs_dir2_sf_entry *)
> - ((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
> - * offset after the inode number. Because it's only a single byte, endian
> - * conversion is not necessary.
> - */
> -static inline __uint8_t *
> -xfs_dir3_sfe_ftypep(
> - struct xfs_dir2_sf_hdr *hdr,
> - struct xfs_dir2_sf_entry *sfep)
> -{
> - return (__uint8_t *)&sfep->name[sfep->namelen];
> -}
> -
> -static inline __uint8_t
> -xfs_dir3_sfe_get_ftype(
> - struct xfs_mount *mp,
> - struct xfs_dir2_sf_hdr *hdr,
> - struct xfs_dir2_sf_entry *sfep)
> -{
> - __uint8_t *ftp;
> -
> - if (!xfs_sb_version_hasftype(&mp->m_sb))
> - return XFS_DIR3_FT_UNKNOWN;
> -
> - ftp = xfs_dir3_sfe_ftypep(hdr, sfep);
> - if (*ftp >= XFS_DIR3_FT_MAX)
> - return XFS_DIR3_FT_UNKNOWN;
> - return *ftp;
> -}
> -
> -static inline void
> -xfs_dir3_sfe_put_ftype(
> - struct xfs_mount *mp,
> - struct xfs_dir2_sf_hdr *hdr,
> - struct xfs_dir2_sf_entry *sfep,
> - __uint8_t ftype)
> -{
> - __uint8_t *ftp;
> -
> - ASSERT(ftype < XFS_DIR3_FT_MAX);
> -
> - if (!xfs_sb_version_hasftype(&mp->m_sb))
> - return;
> - ftp = xfs_dir3_sfe_ftypep(hdr, sfep);
> - *ftp = ftype;
> -}
> -
> -/*
> - * Data block structures.
> - *
> - * A pure data block looks like the following drawing on disk:
> - *
> - * +-------------------------------------------------+
> - * | xfs_dir2_data_hdr_t |
> - * +-------------------------------------------------+
> - * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t |
> - * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t |
> - * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t |
> - * | ... |
> - * +-------------------------------------------------+
> - * | unused space |
> - * +-------------------------------------------------+
> - *
> - * As all the entries are variable size structures the accessors below should
> - * be used to iterate over them.
> - *
> - * In addition to the pure data blocks for the data and node formats,
> - * most structures are also used for the combined data/freespace "block"
> - * format below.
> - */
> -
> -#define XFS_DIR2_DATA_ALIGN_LOG 3 /* i.e., 8 bytes */
> -#define XFS_DIR2_DATA_ALIGN (1 << XFS_DIR2_DATA_ALIGN_LOG)
> -#define XFS_DIR2_DATA_FREE_TAG 0xffff
> -#define XFS_DIR2_DATA_FD_COUNT 3
> -
> -/*
> - * Directory address space divided into sections,
> - * spaces separated by 32GB.
> - */
> -#define XFS_DIR2_SPACE_SIZE (1ULL << (32 + XFS_DIR2_DATA_ALIGN_LOG))
> -#define XFS_DIR2_DATA_SPACE 0
> -#define XFS_DIR2_DATA_OFFSET (XFS_DIR2_DATA_SPACE * XFS_DIR2_SPACE_SIZE)
> -#define XFS_DIR2_DATA_FIRSTDB(mp) \
> - xfs_dir2_byte_to_db(mp, XFS_DIR2_DATA_OFFSET)
> -
> -/*
> - * Describe a free area in the data block.
> - *
> - * The freespace will be formatted as a xfs_dir2_data_unused_t.
> - */
> -typedef struct xfs_dir2_data_free {
> - __be16 offset; /* start of freespace */
> - __be16 length; /* length of freespace */
> -} xfs_dir2_data_free_t;
> -
> -/*
> - * Header for the data blocks.
> - *
> - * The code knows that XFS_DIR2_DATA_FD_COUNT is 3.
> - */
> -typedef struct xfs_dir2_data_hdr {
> - __be32 magic; /* XFS_DIR2_DATA_MAGIC or */
> - /* XFS_DIR2_BLOCK_MAGIC */
> - xfs_dir2_data_free_t bestfree[XFS_DIR2_DATA_FD_COUNT];
> -} xfs_dir2_data_hdr_t;
> -
> -/*
> - * define a structure for all the verification fields we are adding to the
> - * directory block structures. This will be used in several structures.
> - * The magic number must be the first entry to align with all the dir2
> - * structures so we determine how to decode them just by the magic number.
> - */
> -struct xfs_dir3_blk_hdr {
> - __be32 magic; /* magic number */
> - __be32 crc; /* CRC of block */
> - __be64 blkno; /* first block of the buffer */
> - __be64 lsn; /* sequence number of last write */
> - uuid_t uuid; /* filesystem we belong to */
> - __be64 owner; /* inode that owns the block */
> -};
> -
> -struct xfs_dir3_data_hdr {
> - struct xfs_dir3_blk_hdr hdr;
> - xfs_dir2_data_free_t best_free[XFS_DIR2_DATA_FD_COUNT];
> - __be32 pad; /* 64 bit alignment */
> -};
> -
> -#define XFS_DIR3_DATA_CRC_OFF offsetof(struct xfs_dir3_data_hdr, hdr.crc)
> -
> -static inline struct xfs_dir2_data_free *
> -xfs_dir3_data_bestfree_p(struct xfs_dir2_data_hdr *hdr)
> -{
> - if (hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
> - hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) {
> - struct xfs_dir3_data_hdr *hdr3 = (struct xfs_dir3_data_hdr *)hdr;
> - return hdr3->best_free;
> - }
> - return hdr->bestfree;
> -}
> -
> -/*
> - * Active entry in a data block.
> - *
> - * Aligned to 8 bytes. After the variable length name field there is a
> - * 2 byte tag field, which can be accessed using xfs_dir3_data_entry_tag_p.
> - *
> - * For dir3 structures, there is file type field between the name and the tag.
> - * This can only be manipulated by helper functions. It is packed hard against
> - * the end of the name so any padding for rounding is between the file type and
> - * the tag.
> - */
> -typedef struct xfs_dir2_data_entry {
> - __be64 inumber; /* inode number */
> - __u8 namelen; /* name length */
> - __u8 name[]; /* name bytes, no null */
> - /* __u8 filetype; */ /* type of inode we point to */
> - /* __be16 tag; */ /* starting offset of us */
> -} xfs_dir2_data_entry_t;
> -
> -/*
> - * Unused entry in a data block.
> - *
> - * Aligned to 8 bytes. Tag appears as the last 2 bytes and must be accessed
> - * using xfs_dir2_data_unused_tag_p.
> - */
> -typedef struct xfs_dir2_data_unused {
> - __be16 freetag; /* XFS_DIR2_DATA_FREE_TAG */
> - __be16 length; /* total free length */
> - /* variable offset */
> - __be16 tag; /* starting offset of us */
> -} xfs_dir2_data_unused_t;
> -
> -/*
> - * Size of a data entry.
> - */
> -static inline 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 inline int
> -xfs_dir3_data_entsize(
> - struct xfs_mount *mp,
> - int n)
> -{
> - bool ftype = xfs_sb_version_hasftype(&mp->m_sb) ? true : false;
> - return __xfs_dir3_data_entsize(ftype, n);
> -}
> -
> -static inline __uint8_t
> -xfs_dir3_dirent_get_ftype(
> - struct xfs_mount *mp,
> - struct xfs_dir2_data_entry *dep)
> -{
> - if (xfs_sb_version_hasftype(&mp->m_sb)) {
> - __uint8_t type = dep->name[dep->namelen];
> -
> - ASSERT(type < XFS_DIR3_FT_MAX);
> - if (type < XFS_DIR3_FT_MAX)
> - return type;
> -
> - }
> - return XFS_DIR3_FT_UNKNOWN;
> -}
> -
> -static inline void
> -xfs_dir3_dirent_put_ftype(
> - struct xfs_mount *mp,
> - struct xfs_dir2_data_entry *dep,
> - __uint8_t type)
> -{
> - ASSERT(type < XFS_DIR3_FT_MAX);
> - ASSERT(dep->namelen != 0);
> -
> - if (xfs_sb_version_hasftype(&mp->m_sb))
> - dep->name[dep->namelen] = type;
> -}
> -
> -/*
> - * Pointer to an entry's tag word.
> - */
> -static inline __be16 *
> -xfs_dir3_data_entry_tag_p(
> - struct xfs_mount *mp,
> - struct xfs_dir2_data_entry *dep)
> -{
> - return (__be16 *)((char *)dep +
> - xfs_dir3_data_entsize(mp, dep->namelen) - sizeof(__be16));
> -}
> -
> -/*
> - * Pointer to a freespace's tag word.
> - */
> -static inline __be16 *
> -xfs_dir2_data_unused_tag_p(struct xfs_dir2_data_unused *dup)
> -{
> - return (__be16 *)((char *)dup +
> - be16_to_cpu(dup->length) - sizeof(__be16));
> -}
> -
> -static inline size_t
> -xfs_dir3_data_hdr_size(bool dir3)
> -{
> - if (dir3)
> - return sizeof(struct xfs_dir3_data_hdr);
> - return sizeof(struct xfs_dir2_data_hdr);
> -}
> -
> -static inline size_t
> -xfs_dir3_data_entry_offset(struct xfs_dir2_data_hdr *hdr)
> -{
> - bool dir3 = hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
> - hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC);
> - return xfs_dir3_data_hdr_size(dir3);
> -}
> -
> -static inline 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(hdr));
> -}
> -
> -static inline 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(hdr));
> -}
> -
> -/*
> - * Offsets of . and .. in data space (always block 0)
> - *
> - * XXX: there is scope for significant optimisation of the logic here. Right
> - * now we are checking for "dir3 format" over and over again. Ideally we should
> - * only do it once for each operation.
> - */
> -static inline xfs_dir2_data_aoff_t
> -xfs_dir3_data_dot_offset(struct xfs_mount *mp)
> -{
> - return xfs_dir3_data_hdr_size(xfs_sb_version_hascrc(&mp->m_sb));
> -}
> -
> -static inline xfs_dir2_data_aoff_t
> -xfs_dir3_data_dotdot_offset(struct xfs_mount *mp)
> -{
> - return xfs_dir3_data_dot_offset(mp) +
> - xfs_dir3_data_entsize(mp, 1);
> -}
> -
> -static inline xfs_dir2_data_aoff_t
> -xfs_dir3_data_first_offset(struct xfs_mount *mp)
> -{
> - return xfs_dir3_data_dotdot_offset(mp) +
> - xfs_dir3_data_entsize(mp, 2);
> -}
> -
> -/*
> - * location of . and .. in data space (always block 0)
> - */
> -static inline struct xfs_dir2_data_entry *
> -xfs_dir3_data_dot_entry_p(
> - struct xfs_mount *mp,
> - struct xfs_dir2_data_hdr *hdr)
> -{
> - return (struct xfs_dir2_data_entry *)
> - ((char *)hdr + xfs_dir3_data_dot_offset(mp));
> -}
> -
> -static inline struct xfs_dir2_data_entry *
> -xfs_dir3_data_dotdot_entry_p(
> - struct xfs_mount *mp,
> - struct xfs_dir2_data_hdr *hdr)
> -{
> - return (struct xfs_dir2_data_entry *)
> - ((char *)hdr + xfs_dir3_data_dotdot_offset(mp));
> -}
> -
> -static inline struct xfs_dir2_data_entry *
> -xfs_dir3_data_first_entry_p(
> - struct xfs_mount *mp,
> - struct xfs_dir2_data_hdr *hdr)
> -{
> - return (struct xfs_dir2_data_entry *)
> - ((char *)hdr + xfs_dir3_data_first_offset(mp));
> -}
> -
> -/*
> - * Leaf block structures.
> - *
> - * A pure leaf block looks like the following drawing on disk:
> - *
> - * +---------------------------+
> - * | xfs_dir2_leaf_hdr_t |
> - * +---------------------------+
> - * | xfs_dir2_leaf_entry_t |
> - * | xfs_dir2_leaf_entry_t |
> - * | xfs_dir2_leaf_entry_t |
> - * | xfs_dir2_leaf_entry_t |
> - * | ... |
> - * +---------------------------+
> - * | xfs_dir2_data_off_t |
> - * | xfs_dir2_data_off_t |
> - * | xfs_dir2_data_off_t |
> - * | ... |
> - * +---------------------------+
> - * | xfs_dir2_leaf_tail_t |
> - * +---------------------------+
> - *
> - * The xfs_dir2_data_off_t members (bests) and tail are at the end of the block
> - * for single-leaf (magic = XFS_DIR2_LEAF1_MAGIC) blocks only, but not present
> - * for directories with separate leaf nodes and free space blocks
> - * (magic = XFS_DIR2_LEAFN_MAGIC).
> - *
> - * As all the entries are variable size structures the accessors below should
> - * be used to iterate over them.
> - */
> -
> -/*
> - * Offset of the leaf/node space. First block in this space
> - * is the btree root.
> - */
> -#define XFS_DIR2_LEAF_SPACE 1
> -#define XFS_DIR2_LEAF_OFFSET (XFS_DIR2_LEAF_SPACE * XFS_DIR2_SPACE_SIZE)
> -#define XFS_DIR2_LEAF_FIRSTDB(mp) \
> - xfs_dir2_byte_to_db(mp, XFS_DIR2_LEAF_OFFSET)
> -
> -/*
> - * Leaf block header.
> - */
> -typedef struct xfs_dir2_leaf_hdr {
> - xfs_da_blkinfo_t info; /* header for da routines */
> - __be16 count; /* count of entries */
> - __be16 stale; /* count of stale entries */
> -} xfs_dir2_leaf_hdr_t;
> -
> -struct xfs_dir3_leaf_hdr {
> - struct xfs_da3_blkinfo info; /* header for da routines */
> - __be16 count; /* count of entries */
> - __be16 stale; /* count of stale entries */
> - __be32 pad; /* 64 bit alignment */
> -};
> -
> -struct xfs_dir3_icleaf_hdr {
> - __uint32_t forw;
> - __uint32_t back;
> - __uint16_t magic;
> - __uint16_t count;
> - __uint16_t stale;
> -};
> -
> -/*
> - * Leaf block entry.
> - */
> -typedef struct xfs_dir2_leaf_entry {
> - __be32 hashval; /* hash value of name */
> - __be32 address; /* address of data entry */
> -} xfs_dir2_leaf_entry_t;
> -
> -/*
> - * Leaf block tail.
> - */
> -typedef struct xfs_dir2_leaf_tail {
> - __be32 bestcount;
> -} xfs_dir2_leaf_tail_t;
> -
> -/*
> - * Leaf block.
> - */
> -typedef struct xfs_dir2_leaf {
> - xfs_dir2_leaf_hdr_t hdr; /* leaf header */
> - xfs_dir2_leaf_entry_t __ents[]; /* entries */
> -} xfs_dir2_leaf_t;
> -
> -struct xfs_dir3_leaf {
> - struct xfs_dir3_leaf_hdr hdr; /* leaf header */
> - struct xfs_dir2_leaf_entry __ents[]; /* entries */
> -};
> -
> -#define XFS_DIR3_LEAF_CRC_OFF offsetof(struct xfs_dir3_leaf_hdr, info.crc)
> -
> -extern void xfs_dir3_leaf_hdr_from_disk(struct xfs_dir3_icleaf_hdr *to,
> - struct xfs_dir2_leaf *from);
> -
> -static inline int
> -xfs_dir3_leaf_hdr_size(struct xfs_dir2_leaf *lp)
> -{
> - if (lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) ||
> - lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC))
> - return sizeof(struct xfs_dir3_leaf_hdr);
> - return sizeof(struct xfs_dir2_leaf_hdr);
> -}
> -
> -static inline int
> -xfs_dir3_max_leaf_ents(struct xfs_mount *mp, struct xfs_dir2_leaf *lp)
> -{
> - return (mp->m_dirblksize - xfs_dir3_leaf_hdr_size(lp)) /
> - (uint)sizeof(struct xfs_dir2_leaf_entry);
> -}
> -
> -/*
> - * Get address of the bestcount field in the single-leaf block.
> - */
> -static inline struct xfs_dir2_leaf_entry *
> -xfs_dir3_leaf_ents_p(struct xfs_dir2_leaf *lp)
> -{
> - if (lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) ||
> - lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)) {
> - struct xfs_dir3_leaf *lp3 = (struct xfs_dir3_leaf *)lp;
> - return lp3->__ents;
> - }
> - return lp->__ents;
> -}
> -
> -/*
> - * Get address of the bestcount field in the single-leaf block.
> - */
> -static inline struct xfs_dir2_leaf_tail *
> -xfs_dir2_leaf_tail_p(struct xfs_mount *mp, struct xfs_dir2_leaf *lp)
> -{
> - return (struct xfs_dir2_leaf_tail *)
> - ((char *)lp + mp->m_dirblksize -
> - sizeof(struct xfs_dir2_leaf_tail));
> -}
> -
> -/*
> - * Get address of the bests array in the single-leaf block.
> - */
> -static inline __be16 *
> -xfs_dir2_leaf_bests_p(struct xfs_dir2_leaf_tail *ltp)
> -{
> - return (__be16 *)ltp - be32_to_cpu(ltp->bestcount);
> -}
> -
> -/*
> - * DB blocks here are logical directory block numbers, not filesystem blocks.
> - */
> -
> -/*
> - * Convert dataptr to byte in file space
> - */
> -static inline xfs_dir2_off_t
> -xfs_dir2_dataptr_to_byte(struct xfs_mount *mp, xfs_dir2_dataptr_t dp)
> -{
> - return (xfs_dir2_off_t)dp << XFS_DIR2_DATA_ALIGN_LOG;
> -}
> -
> -/*
> - * Convert byte in file space to dataptr. It had better be aligned.
> - */
> -static inline xfs_dir2_dataptr_t
> -xfs_dir2_byte_to_dataptr(struct xfs_mount *mp, xfs_dir2_off_t by)
> -{
> - return (xfs_dir2_dataptr_t)(by >> XFS_DIR2_DATA_ALIGN_LOG);
> -}
> -
> -/*
> - * Convert byte in space to (DB) block
> - */
> -static inline xfs_dir2_db_t
> -xfs_dir2_byte_to_db(struct xfs_mount *mp, xfs_dir2_off_t by)
> -{
> - return (xfs_dir2_db_t)
> - (by >> (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog));
> -}
> -
> -/*
> - * Convert dataptr to a block number
> - */
> -static inline xfs_dir2_db_t
> -xfs_dir2_dataptr_to_db(struct xfs_mount *mp, xfs_dir2_dataptr_t dp)
> -{
> - return xfs_dir2_byte_to_db(mp, xfs_dir2_dataptr_to_byte(mp, dp));
> -}
> -
> -/*
> - * Convert byte in space to offset in a block
> - */
> -static inline xfs_dir2_data_aoff_t
> -xfs_dir2_byte_to_off(struct xfs_mount *mp, xfs_dir2_off_t by)
> -{
> - return (xfs_dir2_data_aoff_t)(by &
> - ((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) - 1));
> -}
> -
> -/*
> - * Convert dataptr to a byte offset in a block
> - */
> -static inline xfs_dir2_data_aoff_t
> -xfs_dir2_dataptr_to_off(struct xfs_mount *mp, xfs_dir2_dataptr_t dp)
> -{
> - return xfs_dir2_byte_to_off(mp, xfs_dir2_dataptr_to_byte(mp, dp));
> -}
> -
> -/*
> - * Convert block and offset to byte in space
> - */
> -static inline xfs_dir2_off_t
> -xfs_dir2_db_off_to_byte(struct xfs_mount *mp, xfs_dir2_db_t db,
> - xfs_dir2_data_aoff_t o)
> -{
> - return ((xfs_dir2_off_t)db <<
> - (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) + o;
> -}
> -
> -/*
> - * Convert block (DB) to block (dablk)
> - */
> -static inline xfs_dablk_t
> -xfs_dir2_db_to_da(struct xfs_mount *mp, xfs_dir2_db_t db)
> -{
> - return (xfs_dablk_t)(db << mp->m_sb.sb_dirblklog);
> -}
> -
> -/*
> - * Convert byte in space to (DA) block
> - */
> -static inline xfs_dablk_t
> -xfs_dir2_byte_to_da(struct xfs_mount *mp, xfs_dir2_off_t by)
> -{
> - return xfs_dir2_db_to_da(mp, xfs_dir2_byte_to_db(mp, by));
> -}
> -
> -/*
> - * Convert block and offset to dataptr
> - */
> -static inline xfs_dir2_dataptr_t
> -xfs_dir2_db_off_to_dataptr(struct xfs_mount *mp, xfs_dir2_db_t db,
> - xfs_dir2_data_aoff_t o)
> -{
> - return xfs_dir2_byte_to_dataptr(mp, xfs_dir2_db_off_to_byte(mp, db, o));
> -}
> -
> -/*
> - * Convert block (dablk) to block (DB)
> - */
> -static inline xfs_dir2_db_t
> -xfs_dir2_da_to_db(struct xfs_mount *mp, xfs_dablk_t da)
> -{
> - return (xfs_dir2_db_t)(da >> mp->m_sb.sb_dirblklog);
> -}
> -
> -/*
> - * Convert block (dablk) to byte offset in space
> - */
> -static inline xfs_dir2_off_t
> -xfs_dir2_da_to_byte(struct xfs_mount *mp, xfs_dablk_t da)
> -{
> - return xfs_dir2_db_off_to_byte(mp, xfs_dir2_da_to_db(mp, da), 0);
> -}
> -
> -/*
> - * Free space block defintions for the node format.
> - */
> -
> -/*
> - * Offset of the freespace index.
> - */
> -#define XFS_DIR2_FREE_SPACE 2
> -#define XFS_DIR2_FREE_OFFSET (XFS_DIR2_FREE_SPACE * XFS_DIR2_SPACE_SIZE)
> -#define XFS_DIR2_FREE_FIRSTDB(mp) \
> - xfs_dir2_byte_to_db(mp, XFS_DIR2_FREE_OFFSET)
> -
> -typedef struct xfs_dir2_free_hdr {
> - __be32 magic; /* XFS_DIR2_FREE_MAGIC */
> - __be32 firstdb; /* db of first entry */
> - __be32 nvalid; /* count of valid entries */
> - __be32 nused; /* count of used entries */
> -} xfs_dir2_free_hdr_t;
> -
> -typedef struct xfs_dir2_free {
> - xfs_dir2_free_hdr_t hdr; /* block header */
> - __be16 bests[]; /* best free counts */
> - /* unused entries are -1 */
> -} xfs_dir2_free_t;
> -
> -struct xfs_dir3_free_hdr {
> - struct xfs_dir3_blk_hdr hdr;
> - __be32 firstdb; /* db of first entry */
> - __be32 nvalid; /* count of valid entries */
> - __be32 nused; /* count of used entries */
> - __be32 pad; /* 64 bit alignment */
> -};
> -
> -struct xfs_dir3_free {
> - struct xfs_dir3_free_hdr hdr;
> - __be16 bests[]; /* best free counts */
> - /* unused entries are -1 */
> -};
> -
> -#define XFS_DIR3_FREE_CRC_OFF offsetof(struct xfs_dir3_free, hdr.hdr.crc)
> -
> -/*
> - * In core version of the free block header, abstracted away from on-disk format
> - * differences. Use this in the code, and convert to/from the disk version using
> - * xfs_dir3_free_hdr_from_disk/xfs_dir3_free_hdr_to_disk.
> - */
> -struct xfs_dir3_icfree_hdr {
> - __uint32_t magic;
> - __uint32_t firstdb;
> - __uint32_t nvalid;
> - __uint32_t nused;
> -
> -};
> -
> -void xfs_dir3_free_hdr_from_disk(struct xfs_dir3_icfree_hdr *to,
> - struct xfs_dir2_free *from);
> -
> -static inline int
> -xfs_dir3_free_hdr_size(struct xfs_mount *mp)
> -{
> - if (xfs_sb_version_hascrc(&mp->m_sb))
> - return sizeof(struct xfs_dir3_free_hdr);
> - return sizeof(struct xfs_dir2_free_hdr);
> -}
> -
> -static inline int
> -xfs_dir3_free_max_bests(struct xfs_mount *mp)
> -{
> - return (mp->m_dirblksize - xfs_dir3_free_hdr_size(mp)) /
> - sizeof(xfs_dir2_data_off_t);
> -}
> -
> -static inline __be16 *
> -xfs_dir3_free_bests_p(struct xfs_mount *mp, struct xfs_dir2_free *free)
> -{
> - return (__be16 *)((char *)free + xfs_dir3_free_hdr_size(mp));
> -}
> -
> -/*
> - * Convert data space db to the corresponding free db.
> - */
> -static inline xfs_dir2_db_t
> -xfs_dir2_db_to_fdb(struct xfs_mount *mp, xfs_dir2_db_t db)
> -{
> - return XFS_DIR2_FREE_FIRSTDB(mp) + db / xfs_dir3_free_max_bests(mp);
> -}
> -
> -/*
> - * Convert data space db to the corresponding index in a free db.
> - */
> -static inline int
> -xfs_dir2_db_to_fdindex(struct xfs_mount *mp, xfs_dir2_db_t db)
> -{
> - return db % xfs_dir3_free_max_bests(mp);
> -}
> -
> -/*
> - * Single block format.
> - *
> - * The single block format looks like the following drawing on disk:
> - *
> - * +-------------------------------------------------+
> - * | xfs_dir2_data_hdr_t |
> - * +-------------------------------------------------+
> - * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t |
> - * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t |
> - * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t :
> - * | ... |
> - * +-------------------------------------------------+
> - * | unused space |
> - * +-------------------------------------------------+
> - * | ... |
> - * | xfs_dir2_leaf_entry_t |
> - * | xfs_dir2_leaf_entry_t |
> - * +-------------------------------------------------+
> - * | xfs_dir2_block_tail_t |
> - * +-------------------------------------------------+
> - *
> - * As all the entries are variable size structures the accessors below should
> - * be used to iterate over them.
> - */
> -
> -typedef struct xfs_dir2_block_tail {
> - __be32 count; /* count of leaf entries */
> - __be32 stale; /* count of stale lf entries */
> -} xfs_dir2_block_tail_t;
> -
> -/*
> - * Pointer to the leaf header embedded in a data block (1-block format)
> - */
> -static inline struct xfs_dir2_block_tail *
> -xfs_dir2_block_tail_p(struct xfs_mount *mp, struct xfs_dir2_data_hdr *hdr)
> -{
> - return ((struct xfs_dir2_block_tail *)
> - ((char *)hdr + mp->m_dirblksize)) - 1;
> -}
> -
> -/*
> - * Pointer to the leaf entries embedded in a data block (1-block format)
> - */
> -static inline struct xfs_dir2_leaf_entry *
> -xfs_dir2_block_leaf_p(struct xfs_dir2_block_tail *btp)
> -{
> - return ((struct xfs_dir2_leaf_entry *)btp) - be32_to_cpu(btp->count);
> -}
> -
> -#endif /* __XFS_DIR2_FORMAT_H__ */
>
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [PATCH 02/32] libxfs: fix missing filetype updates to xfs_dir2.c
2013-09-30 3:15 ` [PATCH 02/32] libxfs: fix missing filetype updates to xfs_dir2.c Dave Chinner
2013-10-08 22:53 ` Eric Sandeen
@ 2013-10-18 16:45 ` Rich Johnston
1 sibling, 0 replies; 56+ messages in thread
From: Rich Johnston @ 2013-10-18 16:45 UTC (permalink / raw)
To: Dave Chinner, xfs
This has been committed.
Thanks
--Rich
commit f7e01baf653a566c1772929629791fc65ef4b120
Author: Dave Chinner <dchinner@redhat.com>
Date: Mon Sep 30 03:15:14 2013 +0000
libxfs: fix missing filetype updates to xfs_dir2.c
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [PATCH 05/32] xfs: ensure we copy buffer type in da btree root splits
2013-09-30 3:15 ` [PATCH 05/32] xfs: ensure we copy buffer type in da btree root splits Dave Chinner
2013-10-08 23:06 ` Eric Sandeen
@ 2013-10-18 16:49 ` Rich Johnston
1 sibling, 0 replies; 56+ messages in thread
From: Rich Johnston @ 2013-10-18 16:49 UTC (permalink / raw)
To: Dave Chinner, xfs
This has been committed.
Thanks
--Rich
commit e26915ee1e90908a686dd8aa5f7b88de903e9da2
Author: Dave Chinner <dchinner@redhat.com>
Date: Mon Sep 30 03:15:17 2013 +0000
xfs: ensure we copy buffer type in da btree root splits
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [PATCH 08/32] xfs: create a shared header file for format-related information
2013-09-30 3:15 ` [PATCH 08/32] xfs: create a shared header file for format-related information Dave Chinner
2013-10-08 23:37 ` Eric Sandeen
@ 2013-10-18 16:59 ` Rich Johnston
2013-10-18 22:40 ` Dave Chinner
1 sibling, 1 reply; 56+ messages in thread
From: Rich Johnston @ 2013-10-18 16:59 UTC (permalink / raw)
To: Dave Chinner, xfs
This has been committed.
Thanks
--Rich
commit dd297fd6d366f62ca2f579e510e6287699d0bd5d
Author: Dave Chinner <david@fromorbit.com>
Date: Mon Sep 30 03:15:20 2013 +0000
xfs: create a shared header file for format-related information
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [PATCH 09/32] xfs: unify directory/attribute format definitions
2013-09-30 3:15 ` [PATCH 09/32] xfs: unify directory/attribute format definitions Dave Chinner
2013-10-14 20:44 ` Eric Sandeen
@ 2013-10-18 20:32 ` Rich Johnston
2013-10-22 22:25 ` Dave Chinner
1 sibling, 1 reply; 56+ messages in thread
From: Rich Johnston @ 2013-10-18 20:32 UTC (permalink / raw)
To: Dave Chinner, xfs
Sorry Dave i did not realize I needed to do a make clean first.
This has been commited.
Thanks
--Rich
commit ddd5a16201db90a255952f61c34aeaab67d0a845
Author: Dave Chinner <dchinner@redhat.com>
Date: Mon Sep 30 03:15:21 2013 +0000
xfs: unify directory/attribute format definitions
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [PATCH 07/32] xfs: dirent dtype presence is dependent on directory magic numbers
2013-10-08 23:30 ` Eric Sandeen
2013-10-09 20:51 ` Dave Chinner
@ 2013-10-18 22:38 ` Rich Johnston
1 sibling, 0 replies; 56+ messages in thread
From: Rich Johnston @ 2013-10-18 22:38 UTC (permalink / raw)
To: Eric Sandeen, Dave Chinner; +Cc: xfs
commit 41315687d9db9b50876401e7b0ee20dd77cfc712
Author: Dave Chinner <dchinner@redhat.com>
Date: Mon Sep 30 03:15:19 2013 +0000
xfs: dirent dtype presence is dependent on directory magic numbers
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [PATCH 08/32] xfs: create a shared header file for format-related information
2013-10-18 16:59 ` Rich Johnston
@ 2013-10-18 22:40 ` Dave Chinner
2013-10-18 22:43 ` Rich Johnston
2013-10-22 18:07 ` Rich Johnston
0 siblings, 2 replies; 56+ messages in thread
From: Dave Chinner @ 2013-10-18 22:40 UTC (permalink / raw)
To: Rich Johnston; +Cc: xfs
On Fri, Oct 18, 2013 at 11:59:23AM -0500, Rich Johnston wrote:
> This has been committed.
>
> Thanks
> --Rich
>
> commit dd297fd6d366f62ca2f579e510e6287699d0bd5d
> Author: Dave Chinner <david@fromorbit.com>
> Date: Mon Sep 30 03:15:20 2013 +0000
>
> xfs: create a shared header file for format-related information
Rich, none of the kernel patches for this rework have been committed
yet. I appreciate you catching up on outstanding patches, but lets
not jump the gun completely by commit stuff to userspace that isn't
yet in the kernel tree.
As it is, the last version of the kernel patch for this change was
slightly modified due to review comments, which is why we should be
waiting for the kernel commits to shared files before finalising
and committing the userspace patches...
Cheers,
Dave.
--
Dave Chinner
david@fromorbit.com
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [PATCH 08/32] xfs: create a shared header file for format-related information
2013-10-18 22:40 ` Dave Chinner
@ 2013-10-18 22:43 ` Rich Johnston
2013-10-22 18:07 ` Rich Johnston
1 sibling, 0 replies; 56+ messages in thread
From: Rich Johnston @ 2013-10-18 22:43 UTC (permalink / raw)
To: Dave Chinner; +Cc: xfs
Sorry that's why I responded to the wrong thread for patch 07/32
On 10/18/2013 05:40 PM, Dave Chinner wrote:
> On Fri, Oct 18, 2013 at 11:59:23AM -0500, Rich Johnston wrote:
>> This has been committed.
>>
>> Thanks
>> --Rich
>>
>> commit dd297fd6d366f62ca2f579e510e6287699d0bd5d
>> Author: Dave Chinner <david@fromorbit.com>
>> Date: Mon Sep 30 03:15:20 2013 +0000
>>
>> xfs: create a shared header file for format-related information
>
> Rich, none of the kernel patches for this rework have been committed
> yet. I appreciate you catching up on outstanding patches, but lets
> not jump the gun completely by commit stuff to userspace that isn't
> yet in the kernel tree.
>
> As it is, the last version of the kernel patch for this change was
> slightly modified due to review comments, which is why we should be
> waiting for the kernel commits to shared files before finalising
> and committing the userspace patches...
>
> Cheers,
>
> Dave.
>
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [PATCH 08/32] xfs: create a shared header file for format-related information
2013-10-18 22:40 ` Dave Chinner
2013-10-18 22:43 ` Rich Johnston
@ 2013-10-22 18:07 ` Rich Johnston
1 sibling, 0 replies; 56+ messages in thread
From: Rich Johnston @ 2013-10-22 18:07 UTC (permalink / raw)
To: Dave Chinner; +Cc: xfs
On 10/18/2013 05:40 PM, Dave Chinner wrote:
> On Fri, Oct 18, 2013 at 11:59:23AM -0500, Rich Johnston wrote:
>> This has been committed.
>>
>> Thanks
>> --Rich
>>
>> commit dd297fd6d366f62ca2f579e510e6287699d0bd5d
>> Author: Dave Chinner <david@fromorbit.com>
>> Date: Mon Sep 30 03:15:20 2013 +0000
>>
>> xfs: create a shared header file for format-related information
>
> Rich, none of the kernel patches for this rework have been committed
> yet. I appreciate you catching up on outstanding patches, but lets
> not jump the gun completely by commit stuff to userspace that isn't
> yet in the kernel tree.
>
> As it is, the last version of the kernel patch for this change was
> slightly modified due to review comments, which is why we should be
> waiting for the kernel commits to shared files before finalising
> and committing the userspace patches...
>
> Cheers,
>
> Dave.
>
commit 77d8143bd059f6da43b46cadaa6a96c3d4573d9c
Author: Rich Johnston <rjohnston@sgi.com>
Date: Tue Oct 22 13:04:53 2013 -0500
Revert "xfs: create a shared header file for format-related
information"
This reverts commit dd297fd6d366f62ca2f579e510e6287699d0bd5d.
Wait for the kernel commits to shared files before finalising
and committing the userspace patches.
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [PATCH 09/32] xfs: unify directory/attribute format definitions
2013-10-18 20:32 ` Rich Johnston
@ 2013-10-22 22:25 ` Dave Chinner
0 siblings, 0 replies; 56+ messages in thread
From: Dave Chinner @ 2013-10-22 22:25 UTC (permalink / raw)
To: Rich Johnston; +Cc: xfs
On Fri, Oct 18, 2013 at 03:32:58PM -0500, Rich Johnston wrote:
> Sorry Dave i did not realize I needed to do a make clean first.
>
> This has been commited.
>
> Thanks
> --Rich
>
> commit ddd5a16201db90a255952f61c34aeaab67d0a845
> Author: Dave Chinner <dchinner@redhat.com>
> Date: Mon Sep 30 03:15:21 2013 +0000
>
> xfs: unify directory/attribute format definitions
FWIW, this is another patch that has not yet been committed to the
kernel code yet.
Cheers,
Dave.
--
Dave Chinner
david@fromorbit.com
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 56+ messages in thread
end of thread, other threads:[~2013-10-22 22:25 UTC | newest]
Thread overview: 56+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <1380510944-8571-1-git-send-email-david@fromorbit.com>
2013-09-30 3:15 ` [PATCH 01/32] xfsprogs: fix automatic dependency generation Dave Chinner
2013-10-08 23:00 ` Eric Sandeen
2013-09-30 3:15 ` [PATCH 02/32] libxfs: fix missing filetype updates to xfs_dir2.c Dave Chinner
2013-10-08 22:53 ` Eric Sandeen
2013-10-09 20:41 ` Dave Chinner
2013-10-18 16:45 ` Rich Johnston
2013-09-30 3:15 ` [PATCH 03/32] xfs: fix some minor sparse warnings Dave Chinner
2013-10-08 22:56 ` Eric Sandeen
2013-10-09 20:43 ` Dave Chinner
2013-09-30 3:15 ` [PATCH 04/32] xfs: check magic numbers in dir3 leaf verifier first Dave Chinner
2013-10-08 23:03 ` Eric Sandeen
2013-10-09 20:45 ` Dave Chinner
2013-10-09 20:50 ` Eric Sandeen
2013-09-30 3:15 ` [PATCH 05/32] xfs: ensure we copy buffer type in da btree root splits Dave Chinner
2013-10-08 23:06 ` Eric Sandeen
2013-10-18 16:49 ` Rich Johnston
2013-09-30 3:15 ` [PATCH 06/32] xfs: don't assert fail on bad inode numbers Dave Chinner
2013-10-08 23:09 ` Eric Sandeen
2013-09-30 3:15 ` [PATCH 07/32] xfs: dirent dtype presence is dependent on directory magic numbers Dave Chinner
2013-10-08 23:30 ` Eric Sandeen
2013-10-09 20:51 ` Dave Chinner
2013-10-09 20:57 ` Eric Sandeen
2013-10-18 22:38 ` Rich Johnston
2013-09-30 3:15 ` [PATCH 08/32] xfs: create a shared header file for format-related information Dave Chinner
2013-10-08 23:37 ` Eric Sandeen
2013-10-18 16:59 ` Rich Johnston
2013-10-18 22:40 ` Dave Chinner
2013-10-18 22:43 ` Rich Johnston
2013-10-22 18:07 ` Rich Johnston
2013-09-30 3:15 ` [PATCH 09/32] xfs: unify directory/attribute format definitions Dave Chinner
2013-10-14 20:44 ` Eric Sandeen
2013-10-18 20:32 ` Rich Johnston
2013-10-22 22:25 ` Dave Chinner
2013-09-30 3:15 ` [PATCH 10/32] xfs: split dquot buffer operations out Dave Chinner
2013-09-30 3:15 ` [PATCH 11/32] xfs: decouple inode and bmap btree header files Dave Chinner
2013-09-30 3:15 ` [PATCH 12/32] libxfs: unify xfs_btree.c with kernel code Dave Chinner
2013-09-30 3:15 ` [PATCH 13/32] libxfs: bmap btree owner swap support Dave Chinner
2013-09-30 3:15 ` [PATCH 14/32] libxfs: xfs_rtalloc.c becomes xfs_rtbitmap.c Dave Chinner
2013-09-30 3:15 ` [PATCH 15/32] libxfs: bring across inode buffer readahead verifier changes Dave Chinner
2013-09-30 3:15 ` [PATCH 16/32] libxfs: Minor cleanup and bug fix sync Dave Chinner
2013-09-30 3:15 ` [PATCH 17/32] db: separate out straight buffer IO from map based IO Dave Chinner
2013-09-30 3:15 ` [PATCH 18/32] db: rewrite bbmap to use xfs_buf_map Dave Chinner
2013-09-30 3:15 ` [PATCH 19/32] db: rewrite IO engine to use libxfs Dave Chinner
2013-09-30 3:15 ` [PATCH 20/32] db: introduce verifier support into set_cur Dave Chinner
2013-09-30 3:15 ` [PATCH 21/32] db: indicate if the CRC on a buffer is correct or not Dave Chinner
2013-09-30 3:15 ` [PATCH 22/32] db: verify and calculate inode CRCs Dave Chinner
2013-09-30 3:15 ` [PATCH 23/32] db: verify and calculate dquot CRCs Dave Chinner
2013-09-30 3:15 ` [PATCH 24/32] db: add a special directory buffer verifier Dave Chinner
2013-09-30 3:15 ` [PATCH 25/32] db: add a special attribute " Dave Chinner
2013-09-30 3:15 ` [PATCH 26/32] db: re-enable write support for v5 filesystems Dave Chinner
2013-09-30 3:15 ` [PATCH 27/32] libxfs: fix root inode handling inconsistencies Dave Chinner
2013-09-30 3:15 ` [PATCH 28/32] xfs_db: avoid libxfs buffer lookup warnings Dave Chinner
2013-09-30 3:15 ` [PATCH 29/32] libxfs: work around do_div() not handling 32 bit numerators Dave Chinner
2013-09-30 3:15 ` [PATCH 30/32] db: enable metadump on CRC filesystems Dave Chinner
2013-09-30 3:15 ` [PATCH 31/32] xfs: support larger inode clusters on v5 filesystems Dave Chinner
2013-09-30 3:15 ` [PATCH 32/32] xfsprogs: kill experimental warnings for " Dave Chinner
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox