xfs: metadata CRCs, third version
cover xfs: metadata CRCs, third version
Hi Folks,
Another week, another version. Previous versions:
http://oss.sgi.com/archives/xfs/2013-01/msg00328.html
http://oss.sgi.com/archives/xfs/2013-02/msg00451.html
This version is based on 3.9-rc2 + TOT xfsdev. I've just forward ported it from a 3.8.0 base where I've been working on it and testing for some time. Bugs that show up are likely to be a result of the forward porting, because I'm posting this before I've even run a full test cycle on 3.9-rc2. I'll probably send delta patches as followup bug fixes rather than reposting full patches, I think...
The first patch is an outstanding bug fix, the second is a change in corruption event output to make it output the entire headers of the corrupted buffer to make it easier to triage problems.
This new version contains:
- numerous bug fixes, mostly in the directory and attribute code.
- support for remote attributes
- directory/attribute buffer type tracking for log recovery
- some cleanup of rough corners in the dir/attr code.
Still to do:
- DT_* type fields in the directory entries
- storage of attributes larger than 256 bytes in shortform attribute forks.
- extended superblock feature field checking (i.e. reject anything that is not zero)
- add mount warnings about CRC support being experimental
- Documentation (half written, not in series)
In terms of testing, this patch set seems quite robust running on non-CRC enabled filesystems with existing tool chains. There are no regressions from xfstests, fsmark, dbench and other worklaods I've thrown at it, nor does there appear to be any significant performance impact from the modified code.
The CRC enabled code has been smoke tested. I haven't finished the userspace port so there is no repair/check functionality which means I cannot run xfstests on it yet. The attribute code is pretty much untested, but everything else seems to work fine. I can run it through my 50-million inode fsmark test (which creates, walks and removes 50 million inodes) without any problems occurring, so directory growing and shrinking is not obviously broken like it was last time.
To run with CRCs enabled, however, you need a mkfs.xfs patch to change the offsets of entries in short form directories. I'l post an updated patch set in the morning that at least enables this in userspace.
Comments, flames and questions welcome.
-Dave.
$ git diff --stat -C -M --summary 929724d.. fs/xfs/Makefile | 6 +- fs/xfs/xfs_ag.h | 56 +- fs/xfs/xfs_alloc.c | 199 ++++-- fs/xfs/xfs_alloc_btree.c | 105 ++- fs/xfs/xfs_alloc_btree.h | 12 +- fs/xfs/xfs_attr.c | 456 +++--------- fs/xfs/xfs_attr.h | 1 - fs/xfs/xfs_attr_leaf.c | 1780 +++++++++++++++++++++++++++-------------------- fs/xfs/xfs_attr_leaf.h | 122 +++- fs/xfs/xfs_attr_remote.c | 550 +++++++++++++++ fs/xfs/xfs_attr_remote.h | 46 ++ fs/xfs/xfs_bmap.c | 71 +- fs/xfs/xfs_bmap_btree.c | 110 ++- fs/xfs/xfs_bmap_btree.h | 19 +- fs/xfs/xfs_btree.c | 256 +++++-- fs/xfs/xfs_btree.h | 64 +- fs/xfs/xfs_buf.c | 6 + fs/xfs/xfs_buf_item.h | 52 +- fs/xfs/xfs_da_btree.c | 1500 ++++++++++++++++++++++++--------------- fs/xfs/xfs_da_btree.h | 130 +++- fs/xfs/xfs_dinode.h | 43 +- fs/xfs/xfs_dir2_block.c | 179 +++-- fs/xfs/xfs_dir2_data.c | 266 ++++--- fs/xfs/xfs_dir2_format.h | 290 +++++++- fs/xfs/xfs_dir2_leaf.c | 891 +++++++++++++++--------- fs/xfs/xfs_dir2_node.c | 992 ++++++++++++++++---------- fs/xfs/xfs_dir2_priv.h | 50 +- fs/xfs/xfs_dir2_sf.c | 12 +- fs/xfs/xfs_dquot.c | 112 ++- fs/xfs/xfs_error.c | 2 +- fs/xfs/xfs_file.c | 2 +- fs/xfs/xfs_fsops.c | 34 +- fs/xfs/xfs_ialloc.c | 80 ++- fs/xfs/xfs_ialloc_btree.c | 87 ++- fs/xfs/xfs_ialloc_btree.h | 9 +- fs/xfs/xfs_inode.c | 212 ++++-- fs/xfs/xfs_inode.h | 31 +- fs/xfs/xfs_inode_item.c | 2 +- fs/xfs/xfs_log_recover.c | 219 +++++- fs/xfs/xfs_mount.c | 97 ++- fs/xfs/xfs_mount.h | 1 + fs/xfs/xfs_qm.c | 23 +- fs/xfs/xfs_qm.h | 2 + fs/xfs/xfs_quota.h | 11 +- fs/xfs/xfs_sb.h | 100 ++- fs/xfs/xfs_symlink.c | 719 +++++++++++++++++++ fs/xfs/xfs_symlink.h | 53 ++ fs/xfs/xfs_trace.c | 2 +- fs/xfs/xfs_trans.h | 4 + fs/xfs/xfs_trans_buf.c | 51 +- fs/xfs/xfs_vnodeops.c | 480 +------------ 51 files changed, 7034 insertions(+), 3563 deletions(-) create mode 100644 fs/xfs/xfs_attr_remote.c create mode 100644 fs/xfs/xfs_attr_remote.h create mode 100644 fs/xfs/xfs_symlink.c create mode 100644 fs/xfs/xfs_symlink.h
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
PATCH 1/21 xfs: ensure we capture IO errors correctly
From: Dave Chinner <[email protected]>
Failed buffer readahead can leave the buffer in the cache marked with an error. Most callers that then issue a subsequent read on the buffer do not zero the b_error field out, and so we may incorectly detect an error during IO completion due to the stale error value left on the buffer.
Avoid this problem by zeroing the error before IO submission. This ensures that the only IO errors that are detected those captured from are those captured from bio submission or completion.
--- fs/xfs/xfs_buf.c | 6 ++++++ 1 file changed, 6 insertions(+)
fs/xfs/xfs_buf.c +6 -0
@@ -1336,6 +1336,12 @@ _xfs_buf_ioapply(int size;int i; +/* +* Make sure we capture only current IO errors rather than stale errors +* left over from previous use of the buffer (e.g. failed readahead). +*/ + bp->b_error =0 ; +if (bp->b_flags &XBF_WRITE ) {if (bp->b_flags &XBF_SYNCIO ) rw =WRITE_SYNC ;
Signature · 6 lines
1.7.10.4 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
PATCH 2/21 xfs: increase hexdump output in xfs_corruption_error
In reply to Dave ChinnerFrom: Dave Chinner <[email protected]>
Currently xfs_corruption_error() dumps the first 16 bytes of the buffer that is passed to it when a corruption occurs. This is not large enough to see the entire state of the header of the block that was determined to be corrupt. increase the output to 64 bytes to capture the majority of all headers in all types of metadata blocks.
--- fs/xfs/xfs_error.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/xfs/xfs_error.c +1 -1
@@ -178,7 +178,7 @@ xfs_corruption_error( inst_t *ra) {if (level <= xfs_error_level) -xfs_hex_dump (p,16 ); +xfs_hex_dump (p,64 );xfs_error_report (tag, level, mp, filename, linenum, ra);xfs_alert (mp,"Corruption detected. Unmount and run xfs_repair" ); }
Signature · 6 lines
1.7.10.4 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 02/21] xfs: increase hexdump output in xfs_corruption_error
Quoted 18 lines · Dave Chinner
From: Dave Chinner <[email protected]>
Currently
xfs_corruption_error()dumps the first 16 bytes of the buffer that is passed to it when a corruption occurs. This is not large enough to see the entire state of the header of the block that was determined to be corrupt. increase the output to 64 bytes to capture the majority of all headers in all types of metadata blocks.Signed-off-by Dave Chinner <[email protected]>--- fs/xfs/xfs_error.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)fs/xfs/xfs_error.c +0
-0
fs/xfs/xfs_error.c xfs_corruption_error( · line 181
Quoted 5 lines
fs/xfs/xfs_error.c +1
-1@@ -178,7 +178,7 @@ xfs_corruption_error( inst_t *ra) {if (level <= xfs_error_level) -xfs_hex_dump (p,16 ); +xfs_hex_dump (p,64 );
Are you sure we don't have any structures which are shorter than that? I guess we'll have to take a look.
-Ben
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 02/21] xfs: increase hexdump output in xfs_corruption_error
Quoted 14 lines · Ben Myers
Quoted 13 lines · Dave Chinner
From: Dave Chinner <[email protected]>
Currently
xfs_corruption_error()dumps the first 16 bytes of the buffer that is passed to it when a corruption occurs. This is not large enough to see the entire state of the header of the block that was determined to be corrupt. increase the output to 64 bytes to capture the majority of all headers in all types of metadata blocks.Signed-off-by Dave Chinner <[email protected]>--- fs/xfs/xfs_error.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Quoted 13 lines
fs/xfs/xfs_error.c xfs_corruption_error( · line 181
Quoted 10 lines
fs/xfs/xfs_error.c +1
-1@@ -178,7 +178,7 @@ xfs_corruption_error( inst_t *ra) {if (level <= xfs_error_level) -xfs_hex_dump (p,16 ); +xfs_hex_dump (p,64 );Are you sure we don't have any structures which are shorter than that? I guess we'll have to take a look.
We only ever pass it buffers or struct xfs_dinode, both of which are always guaranteed to be larger than 64 bytes.
Cheers,
Dave.
Signature · 7 lines
Dave Chinner [email protected] _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
PATCH 3/21 xfs: take inode version into account in XFS_LITINO
In reply to Dave ChinnerFrom: Christoph Hellwig <[email protected]>
Add a version argument to XFS_LITINO so that it can return different values depending on the inode version. This is required for the upcoming v3 inodes with a larger fixed layout dinode.
--- fs/xfs/xfs_attr_leaf.c | 6 ++++-- fs/xfs/xfs_bmap.c | 4 ++-- fs/xfs/xfs_dinode.h | 6 +++--- fs/xfs/xfs_inode.h | 5 +++-- fs/xfs/xfs_vnodeops.c | 2 +- 5 files changed, 13 insertions(+), 10 deletions(-)
fs/xfs/xfs_attr_leaf.c +4 -2
@@ -172,7 +172,8 @@ xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes)int dsize;xfs_mount_t *mp = dp->i_mount; - offset = (XFS_LITINO (mp) - bytes) >>3 ;/* rounded down */ +/* rounded down */ + offset = (XFS_LITINO (mp, dp->i_d.di_version) - bytes) >>3 ;switch (dp->i_d.di_format) {case XFS_DINODE_FMT_DEV :
@@ -243,7 +244,8 @@ xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes) minforkoff =roundup (minforkoff,8 ) >>3 ;/* attr fork btree root can have at least this many key/ptr pairs */ - maxforkoff =XFS_LITINO (mp) -XFS_BMDR_SPACE_CALC (MINABTPTRS ); + maxforkoff =XFS_LITINO (mp, dp->i_d.di_version) - +XFS_BMDR_SPACE_CALC (MINABTPTRS ); maxforkoff = maxforkoff >>3 ;/* rounded down */ if (offset >= maxforkoff)
fs/xfs/xfs_bmap.c +2 -2
@@ -228,13 +228,13 @@ xfs_default_attroffset(uint offset;if (mp->m_sb.sb_inodesize ==256 ) { - offset =XFS_LITINO (mp) - + offset =XFS_LITINO (mp, ip->i_d.di_version) -XFS_BMDR_SPACE_CALC (MINABTPTRS ); }else { offset =XFS_BMDR_SPACE_CALC (6 *MINABTPTRS ); } -ASSERT (offset <XFS_LITINO (mp)); +ASSERT (offset <XFS_LITINO (mp, ip->i_d.di_version));return offset; }
fs/xfs/xfs_dinode.h +3 -3
@@ -104,7 +104,7 @@ typedef enum xfs_dinode_fmt {/* * Inode size for given fs. */ -#define XFS_LITINO (mp) \ +#define XFS_LITINO (mp, version) \ ((int)(((mp)->m_sb.sb_inodesize) - sizeof(struct xfs_dinode)))#define XFS_BROOT_SIZE_ADJ \
@@ -119,10 +119,10 @@ typedef enum xfs_dinode_fmt {#define XFS_DFORK_DSIZE (dip,mp) \ (XFS_DFORK_Q(dip) ? \ XFS_DFORK_BOFF(dip) : \ - XFS_LITINO(mp)) + XFS_LITINO(mp, (dip)->di_version))#define XFS_DFORK_ASIZE (dip,mp) \ (XFS_DFORK_Q(dip) ? \ - XFS_LITINO(mp) - XFS_DFORK_BOFF(dip) : \ + XFS_LITINO(mp, (dip)->di_version) - XFS_DFORK_BOFF(dip) : \ 0)#define XFS_DFORK_SIZE (dip,mp,w) \ ((w) == XFS_DATA_FORK ? \
fs/xfs/xfs_inode.h +3 -2
@@ -180,10 +180,11 @@ typedef struct xfs_icdinode {#define XFS_IFORK_DSIZE (ip) \ (XFS_IFORK_Q(ip) ? \ XFS_IFORK_BOFF(ip) : \ - XFS_LITINO((ip)->i_mount)) + XFS_LITINO((ip)->i_mount, (ip)->i_d.di_version))#define XFS_IFORK_ASIZE (ip) \ (XFS_IFORK_Q(ip) ? \ - XFS_LITINO((ip)->i_mount) - XFS_IFORK_BOFF(ip) : \ + XFS_LITINO((ip)->i_mount, (ip)->i_d.di_version) - \ + XFS_IFORK_BOFF(ip) : \ 0)#define XFS_IFORK_SIZE (ip,w) \ ((w) == XFS_DATA_FORK ? \
fs/xfs/xfs_vnodeops.c +1 -1
@@ -1420,7 +1420,7 @@ xfs_symlink(* The symlink will fit into the inode data fork? * There can't be any attributes so we get the whole variable part. */ -if (pathlen <=XFS_LITINO (mp)) +if (pathlen <=XFS_LITINO (mp, dp->i_d.di_version)) fs_blocks =0 ;else fs_blocks =XFS_B_TO_FSB (mp, pathlen);
Signature · 6 lines
1.7.10.4 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
PATCH 4/21 xfs: add support for large btree blocks
In reply to Dave ChinnerFrom: Christoph Hellwig <[email protected]>
Add support for larger btree blocks that contains a CRC32C checksum, a filesystem uuid and block number for detecting filesystem consistency and out of place writes.
[[email protected]] Also include an owner field to allow reverse mappings to be implemented for improved repairability and a LSN field to so that log recovery can easily determine the last modification that made it to disk for each buffer.
[[email protected]] Add buffer log format flags to indicate the type of buffer to recovery so that we don't have to do blind magic number tests to determine what the buffer is.
[[email protected]] Modified to fit into the verifier structure.
--- fs/xfs/xfs_alloc_btree.c | 105 +++++++++++++------ fs/xfs/xfs_alloc_btree.h | 12 ++- fs/xfs/xfs_attr_leaf.c | 2 +- fs/xfs/xfs_bmap.c | 47 ++++++--- fs/xfs/xfs_bmap_btree.c | 110 +++++++++++++------ fs/xfs/xfs_bmap_btree.h | 19 ++-- fs/xfs/xfs_btree.c | 256 +++++++++++++++++++++++++++++++++++++-------- fs/xfs/xfs_btree.h | 64 ++++++++++-- fs/xfs/xfs_buf_item.h | 24 ++++- fs/xfs/xfs_dinode.h | 4 +- fs/xfs/xfs_fsops.c | 23 +++- fs/xfs/xfs_ialloc_btree.c | 87 ++++++++++----- fs/xfs/xfs_ialloc_btree.h | 9 +- fs/xfs/xfs_inode.c | 33 +++--- fs/xfs/xfs_log_recover.c | 28 +++++ fs/xfs/xfs_trans.h | 2 + fs/xfs/xfs_trans_buf.c | 29 +++-- 17 files changed, 645 insertions(+), 209 deletions(-)
fs/xfs/xfs_alloc_btree.c +73 -32
@@ -33,6 +33,7 @@#include "xfs_extent_busy.h" #include "xfs_error.h" #include "xfs_trace.h" +#include "xfs_cksum.h" STATIC struct xfs_btree_cur *
@@ -272,7 +273,7 @@ xfs_allocbt_key_diff(return (__int64_t )be32_to_cpu (kp->ar_startblock) - rec->ar_startblock; } -static void +static bool xfs_allocbt_verify (struct xfs_buf *bp) {
@@ -280,66 +281,103 @@ xfs_allocbt_verify(struct xfs_btree_block *block =XFS_BUF_TO_BLOCK (bp);struct xfs_perag *pag = bp->b_pag;unsigned int level; -int sblock_ok;/* block passes checks */ /* * magic number and level verification * -* During growfs operations, we can't verify the exact level as the -* perag is not fully initialised and hence not attached to the buffer. -* In this case, check against the maximum tree depth. +* During growfs operations, we can't verify the exact level or owner as +* the perag is not fully initialised and hence not attached to the +* buffer. In this case, check against the maximum tree depth. +* +* Similarly, during log recovery we will have a perag structure +* attached, but the agf information will not yet have been initialised +* from the on disk AGF. Again, we can only check against maximum limits +* in this case. */ level =be16_to_cpu (block->bb_level);switch (block->bb_magic) { +case cpu_to_be32 (XFS_ABTB_CRC_MAGIC ): +if (!xfs_sb_version_hascrc (&mp->m_sb)) +return false; +if (!uuid_equal (&block->bb_u.s.bb_uuid, &mp->m_sb.sb_uuid)) +return false; +if (block->bb_u.s.bb_blkno !=cpu_to_be64 (bp->b_bn)) +return false; +if (pag && +be32_to_cpu (block->bb_u.s.bb_owner) != pag->pag_agno) +return false; +/* fall through */ case cpu_to_be32 (XFS_ABTB_MAGIC ): -if (pag) - sblock_ok = level < pag->pagf_levels[XFS_BTNUM_BNOi]; -else - sblock_ok = level < mp->m_ag_maxlevels; +if (pag && pag->pagf_init) { +if (level >= pag->pagf_levels[XFS_BTNUM_BNOi]) +return false; + }else if (level >= mp->m_ag_maxlevels) +return false;break ; +case cpu_to_be32 (XFS_ABTC_CRC_MAGIC ): +if (!xfs_sb_version_hascrc (&mp->m_sb)) +return false; +if (!uuid_equal (&block->bb_u.s.bb_uuid, &mp->m_sb.sb_uuid)) +return false; +if (block->bb_u.s.bb_blkno !=cpu_to_be64 (bp->b_bn)) +return false; +if (pag && +be32_to_cpu (block->bb_u.s.bb_owner) != pag->pag_agno) +return false; +/* fall through */ case cpu_to_be32 (XFS_ABTC_MAGIC ): -if (pag) - sblock_ok = level < pag->pagf_levels[XFS_BTNUM_CNTi]; -else - sblock_ok = level < mp->m_ag_maxlevels; +if (pag && pag->pagf_init) { +if (level >= pag->pagf_levels[XFS_BTNUM_CNTi]) +return false; + }else if (level >= mp->m_ag_maxlevels) +return false;break ;default : - sblock_ok =0 ; -break ; +return false; }/* numrecs verification */ - sblock_ok = sblock_ok && -be16_to_cpu (block->bb_numrecs) <= mp->m_alloc_mxr[level !=0 ]; +if (be16_to_cpu (block->bb_numrecs) > mp->m_alloc_mxr[level !=0 ]) +return false;/* sibling pointer verification */ - sblock_ok = sblock_ok && - (block->bb_u.s.bb_leftsib ==cpu_to_be32 (NULLAGBLOCK ) || -be32_to_cpu (block->bb_u.s.bb_leftsib) < mp->m_sb.sb_agblocks) && - block->bb_u.s.bb_leftsib && - (block->bb_u.s.bb_rightsib ==cpu_to_be32 (NULLAGBLOCK ) || -be32_to_cpu (block->bb_u.s.bb_rightsib) < mp->m_sb.sb_agblocks) && - block->bb_u.s.bb_rightsib; - -if (!sblock_ok) { -trace_xfs_btree_corrupt (bp, _RET_IP_); -XFS_CORRUPTION_ERROR (__func__,XFS_ERRLEVEL_LOW , mp, block); -xfs_buf_ioerror (bp,EFSCORRUPTED ); - } +if (!block->bb_u.s.bb_leftsib || + (be32_to_cpu (block->bb_u.s.bb_leftsib) >= mp->m_sb.sb_agblocks && + block->bb_u.s.bb_leftsib !=cpu_to_be32 (NULLAGBLOCK ))) +return false; +if (!block->bb_u.s.bb_rightsib || + (be32_to_cpu (block->bb_u.s.bb_rightsib) >= mp->m_sb.sb_agblocks && + block->bb_u.s.bb_rightsib !=cpu_to_be32 (NULLAGBLOCK ))) +return false; + +return true; }static void xfs_allocbt_read_verify (struct xfs_buf *bp) { -xfs_allocbt_verify (bp); +if (!(xfs_btree_sblock_verify_crc (bp) && +xfs_allocbt_verify (bp))) { +trace_xfs_btree_corrupt (bp, _RET_IP_); +XFS_CORRUPTION_ERROR (__func__,XFS_ERRLEVEL_LOW , + bp->b_target->bt_mount, bp->b_addr); +xfs_buf_ioerror (bp,EFSCORRUPTED ); + } }static void xfs_allocbt_write_verify (struct xfs_buf *bp) { -xfs_allocbt_verify (bp); +if (!xfs_allocbt_verify (bp)) { +trace_xfs_btree_corrupt (bp, _RET_IP_); +XFS_CORRUPTION_ERROR (__func__,XFS_ERRLEVEL_LOW , + bp->b_target->bt_mount, bp->b_addr); +xfs_buf_ioerror (bp,EFSCORRUPTED ); + } +xfs_btree_sblock_calc_crc (bp); + }const struct xfs_buf_ops xfs_allocbt_buf_ops = {
@@ -444,6 +482,9 @@ xfs_allocbt_init_cursor( cur->bc_private.a.agbp = agbp; cur->bc_private.a.agno = agno; +if (xfs_sb_version_hascrc (&mp->m_sb)) + cur->bc_flags |=XFS_BTREE_CRC_BLOCKS ; +return cur; }
fs/xfs/xfs_alloc_btree.h +7 -5
@@ -31,8 +31,10 @@ struct xfs_mount;* 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_ABTC_MAGIC 0x41425443/* 'ABTC' for cnt tree */ +#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
@@ -59,10 +61,10 @@ typedef __be32 xfs_alloc_ptr_t;/* * Btree block header size depends on a superblock flag. -* -* (not quite yet, but soon) */ -#define XFS_ALLOC_BLOCK_LEN (mp) XFS_BTREE_SBLOCK_LEN +#define XFS_ALLOC_BLOCK_LEN (mp) \ + (xfs_sb_version_hascrc(&((mp)->m_sb)) ? \ + XFS_BTREE_SBLOCK_CRC_LEN : XFS_BTREE_SBLOCK_LEN)/* * Record, key, and pointer address macros for btree blocks.
fs/xfs/xfs_attr_leaf.c +1 -1
@@ -232,7 +232,7 @@ xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes)return 0 ;return dp->i_d.di_forkoff; } - dsize =XFS_BMAP_BROOT_SPACE (dp->i_df.if_broot); + dsize =XFS_BMAP_BROOT_SPACE (mp, dp->i_df.if_broot);break ; }
fs/xfs/xfs_bmap.c +31 -16
112 lines not on this page · raw message
fs/xfs/xfs_bmap_btree.c +78 -32
180 lines not on this page · raw message
fs/xfs/xfs_bmap_btree.h +10 -9
@@ -18,7 +18,8 @@#ifndef __XFS_BMAP_BTREE_H__#define __XFS_BMAP_BTREE_H__ -#define XFS_BMAP_MAGIC 0x424d4150/* 'BMAP' */ +#define XFS_BMAP_MAGIC 0x424d4150/* 'BMAP' */ +#define XFS_BMAP_CRC_MAGIC 0x424d4133/* 'BMA3' */ struct xfs_btree_cur ;struct xfs_btree_block ;
@@ -136,10 +137,10 @@ typedef __be64 xfs_bmbt_ptr_t, xfs_bmdr_ptr_t;/* * Btree block header size depends on a superblock flag. -* -* (not quite yet, but soon) */ -#define XFS_BMBT_BLOCK_LEN (mp) XFS_BTREE_LBLOCK_LEN +#define XFS_BMBT_BLOCK_LEN (mp) \ + (xfs_sb_version_hascrc(&((mp)->m_sb)) ? \ + XFS_BTREE_LBLOCK_CRC_LEN : XFS_BTREE_LBLOCK_LEN)#define XFS_BMBT_REC_ADDR (mp, block, index) \ ((xfs_bmbt_rec_t *) \
@@ -186,12 +187,12 @@ typedef __be64 xfs_bmbt_ptr_t, xfs_bmdr_ptr_t;#define XFS_BMAP_BROOT_PTR_ADDR (mp, bb, i, sz) \ XFS_BMBT_PTR_ADDR(mp, bb, i, xfs_bmbt_maxrecs(mp, sz, 0)) -#define XFS_BMAP_BROOT_SPACE_CALC (nrecs) \ - (int)(XFS_BTREE_LBLOCK_LEN + \ +#define XFS_BMAP_BROOT_SPACE_CALC (mp, nrecs) \ + (int)(XFS_BMBT_BLOCK_LEN(mp) + \ ((nrecs) * (sizeof(xfs_bmbt_key_t) + sizeof(xfs_bmbt_ptr_t)))) -#define XFS_BMAP_BROOT_SPACE (bb) \ - (XFS_BMAP_BROOT_SPACE_CALC(be16_to_cpu((bb)->bb_numrecs))) +#define XFS_BMAP_BROOT_SPACE (mp, bb) \ + (XFS_BMAP_BROOT_SPACE_CALC(mp, be16_to_cpu((bb)->bb_numrecs)))#define XFS_BMDR_SPACE_CALC (nrecs) \ (int)(sizeof(xfs_bmdr_block_t) + \ ((nrecs) * (sizeof(xfs_bmbt_key_t) + sizeof(xfs_bmbt_ptr_t))))
@@ -204,7 +205,7 @@ typedef __be64 xfs_bmbt_ptr_t, xfs_bmdr_ptr_t;/* * Prototypes for xfs_bmap.c to call. */ -extern void xfs_bmdr_to_bmbt (struct xfs_mount *,xfs_bmdr_block_t *,int , +extern void xfs_bmdr_to_bmbt (struct xfs_inode *,xfs_bmdr_block_t *,int ,struct xfs_btree_block *,int );extern void xfs_bmbt_get_all (xfs_bmbt_rec_host_t *r,xfs_bmbt_irec_t *s);extern xfs_filblks_t xfs_bmbt_get_blockcount (xfs_bmbt_rec_host_t *r);
fs/xfs/xfs_btree.c +211 -45
412 lines not on this page · raw message
fs/xfs/xfs_btree.h +55 -9
115 lines not on this page · raw message
fs/xfs/xfs_buf_item.h +19 -5
@@ -24,19 +24,33 @@ extern kmem_zone_t *xfs_buf_item_zone;* This flag indicates that the buffer contains on disk inodes * and requires special recovery handling. */ -#define XFS_BLF_INODE_BUF 0x1 +#define XFS_BLF_INODE_BUF (1<<0)/* * This flag indicates that the buffer should not be replayed * during recovery because its blocks are being freed. */ -#define XFS_BLF_CANCEL 0x2 +#define XFS_BLF_CANCEL (1<<1) +/* * This flag indicates that the buffer contains on disk * user or group dquots and may require special recovery handling. */ -#define XFS_BLF_UDQUOT_BUF 0x4 -#define XFS_BLF_PDQUOT_BUF 0x8 -#define XFS_BLF_GDQUOT_BUF 0x10 +#define XFS_BLF_UDQUOT_BUF (1<<2) +#define XFS_BLF_PDQUOT_BUF (1<<3) +#define XFS_BLF_GDQUOT_BUF (1<<4) + +/* +* all buffers now need flags to tell recovery where the magic number +* is so that it can verify and calculate the CRCs on the buffer correctly +* once the changes have been replayed into the buffer. +*/ +#define XFS_BLF_BTREE_BUF (1<<5) + +#define XFS_BLF_TYPE_MASK \ + (XFS_BLF_UDQUOT_BUF | \ + XFS_BLF_PDQUOT_BUF | \ + XFS_BLF_GDQUOT_BUF | \ + XFS_BLF_BTREE_BUF)#define XFS_BLF_CHUNK 128#define XFS_BLF_SHIFT 7
fs/xfs/xfs_dinode.h +2 -2
@@ -107,8 +107,8 @@ typedef enum xfs_dinode_fmt {#define XFS_LITINO (mp, version) \ ((int)(((mp)->m_sb.sb_inodesize) - sizeof(struct xfs_dinode))) -#define XFS_BROOT_SIZE_ADJ \ - (XFS_BTREE_LBLOCK_LEN - sizeof(xfs_bmdr_block_t)) +#define XFS_BROOT_SIZE_ADJ (ip) \ + (XFS_BMBT_BLOCK_LEN((ip)->i_mount) - sizeof(xfs_bmdr_block_t))/* * Inode data & attribute fork sizes, per inode.
fs/xfs/xfs_fsops.c +20 -3
@@ -316,7 +316,13 @@ xfs_growfs_data_private( goto error0; } -xfs_btree_init_block (mp, bp,XFS_ABTB_MAGIC ,0 ,1 ,0 ); +if (xfs_sb_version_hascrc (&mp->m_sb)) +xfs_btree_init_block (mp, bp,XFS_ABTB_CRC_MAGIC ,0 ,1 , + agno,XFS_BTREE_CRC_BLOCKS ); +else +xfs_btree_init_block (mp, bp,XFS_ABTB_MAGIC ,0 ,1 , + agno,0 ); + arec =XFS_ALLOC_REC_ADDR (mp,XFS_BUF_TO_BLOCK (bp),1 ); arec->ar_startblock =cpu_to_be32 (XFS_PREALLOC_BLOCKS (mp)); arec->ar_blockcount = cpu_to_be32(
@@ -339,7 +345,13 @@ xfs_growfs_data_private( goto error0; } -xfs_btree_init_block (mp, bp,XFS_ABTC_MAGIC ,0 ,1 ,0 ); +if (xfs_sb_version_hascrc (&mp->m_sb)) +xfs_btree_init_block (mp, bp,XFS_ABTC_CRC_MAGIC ,0 ,1 , + agno,XFS_BTREE_CRC_BLOCKS ); +else +xfs_btree_init_block (mp, bp,XFS_ABTC_MAGIC ,0 ,1 , + agno,0 ); + arec =XFS_ALLOC_REC_ADDR (mp,XFS_BUF_TO_BLOCK (bp),1 ); arec->ar_startblock =cpu_to_be32 (XFS_PREALLOC_BLOCKS (mp)); arec->ar_blockcount = cpu_to_be32(
@@ -363,7 +375,12 @@ xfs_growfs_data_private( goto error0; } -xfs_btree_init_block (mp, bp,XFS_IBT_MAGIC ,0 ,0 ,0 ); +if (xfs_sb_version_hascrc (&mp->m_sb)) +xfs_btree_init_block (mp, bp,XFS_IBT_CRC_MAGIC ,0 ,0 , + agno,XFS_BTREE_CRC_BLOCKS ); +else +xfs_btree_init_block (mp, bp,XFS_IBT_MAGIC ,0 ,0 , + agno,0 ); error =xfs_bwrite (bp);xfs_buf_relse (bp);
fs/xfs/xfs_ialloc_btree.c +63 -24
127 lines not on this page · raw message
fs/xfs/xfs_ialloc_btree.h +5 -4
@@ -29,7 +29,8 @@ struct xfs_mount;/* * There is a btree for the inode map per allocation group. */ -#define XFS_IBT_MAGIC 0x49414254/* 'IABT' */ +#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))
@@ -76,10 +77,10 @@ typedef __be32 xfs_inobt_ptr_t;/* * Btree block header size depends on a superblock flag. -* -* (not quite yet, but soon) */ -#define XFS_INOBT_BLOCK_LEN (mp) XFS_BTREE_SBLOCK_LEN +#define XFS_INOBT_BLOCK_LEN (mp) \ + (xfs_sb_version_hascrc(&((mp)->m_sb)) ? \ + XFS_BTREE_SBLOCK_CRC_LEN : XFS_BTREE_SBLOCK_LEN)/* * Record, key, and pointer address macros for btree blocks.
fs/xfs/xfs_inode.c +17 -16
@@ -786,6 +786,7 @@ xfs_iformat_btree( xfs_dinode_t *dip, int whichfork) { +struct xfs_mount *mp = ip->i_mount;xfs_bmdr_block_t *dfp;xfs_ifork_t *ifp;/* REFERENCED */
@@ -794,7 +795,7 @@ xfs_iformat_btree( ifp =XFS_IFORK_PTR (ip, whichfork); dfp = (xfs_bmdr_block_t *)XFS_DFORK_PTR (dip, whichfork); - size =XFS_BMAP_BROOT_SPACE (dfp); + size =XFS_BMAP_BROOT_SPACE (mp, dfp); nrecs =be16_to_cpu (dfp->bb_numrecs);/*
@@ -805,14 +806,14 @@ xfs_iformat_btree(* blocks. */ if (unlikely (XFS_IFORK_NEXTENTS (ip, whichfork) <= -XFS_IFORK_MAXEXT (ip, whichfork) || +XFS_IFORK_MAXEXT (ip, whichfork) ||XFS_BMDR_SPACE_CALC (nrecs) > -XFS_DFORK_SIZE (dip, ip->i_mount, whichfork) || +XFS_DFORK_SIZE (dip, mp, whichfork) ||XFS_IFORK_NEXTENTS (ip, whichfork) > ip->i_d.di_nblocks)) { -xfs_warn (ip->i_mount,"corrupt inode %Lu (btree)." , - (unsigned long long ) ip->i_ino); +xfs_warn (mp,"corrupt inode %Lu (btree)." , + (unsigned long long ) ip->i_ino);XFS_CORRUPTION_ERROR ("xfs_iformat_btree" ,XFS_ERRLEVEL_LOW , - ip->i_mount, dip); + mp, dip);return XFS_ERROR (EFSCORRUPTED ); }
@@ -823,8 +824,7 @@ xfs_iformat_btree(* Copy and convert from the on-disk structure * to the in-memory structure. */ -xfs_bmdr_to_bmbt (ip->i_mount, dfp, -XFS_DFORK_SIZE (dip, ip->i_mount, whichfork), +xfs_bmdr_to_bmbt (ip, dfp,XFS_DFORK_SIZE (dip, ip->i_mount, whichfork), ifp->if_broot, size); ifp->if_flags &= ~XFS_IFEXTENTS ; ifp->if_flags |=XFS_IFBROOT ;
@@ -2037,7 +2037,7 @@ xfs_iroot_realloc(* allocate it now and get out. */ if (ifp->if_broot_bytes ==0 ) { - new_size = (size_t )XFS_BMAP_BROOT_SPACE_CALC (rec_diff); + new_size =XFS_BMAP_BROOT_SPACE_CALC (mp, rec_diff); ifp->if_broot =kmem_alloc (new_size,KM_SLEEP |KM_NOFS ); ifp->if_broot_bytes = (int )new_size;return ;
@@ -2051,9 +2051,9 @@ xfs_iroot_realloc(*/ cur_max =xfs_bmbt_maxrecs (mp, ifp->if_broot_bytes,0 ); new_max = cur_max + rec_diff; - new_size = (size_t )XFS_BMAP_BROOT_SPACE_CALC (new_max); + new_size =XFS_BMAP_BROOT_SPACE_CALC (mp, new_max); ifp->if_broot =kmem_realloc (ifp->if_broot, new_size, - (size_t )XFS_BMAP_BROOT_SPACE_CALC (cur_max),/* old size */ +XFS_BMAP_BROOT_SPACE_CALC (mp, cur_max),KM_SLEEP |KM_NOFS ); op = (char *)XFS_BMAP_BROOT_PTR_ADDR (mp, ifp->if_broot,1 , ifp->if_broot_bytes);
@@ -2061,7 +2061,7 @@ xfs_iroot_realloc( (int)new_size); ifp->if_broot_bytes = (int )new_size;ASSERT (ifp->if_broot_bytes <= -XFS_IFORK_SIZE (ip, whichfork) +XFS_BROOT_SIZE_ADJ ); +XFS_IFORK_SIZE (ip, whichfork) +XFS_BROOT_SIZE_ADJ (ip));memmove (np, op, cur_max * (uint )sizeof (xfs_dfsbno_t));return ; }
@@ -2076,7 +2076,7 @@ xfs_iroot_realloc( new_max = cur_max + rec_diff;ASSERT (new_max >=0 );if (new_max >0 ) - new_size = (size_t )XFS_BMAP_BROOT_SPACE_CALC (new_max); + new_size =XFS_BMAP_BROOT_SPACE_CALC (mp, new_max);else new_size =0 ;if (new_size >0 ) {
@@ -2084,7 +2084,8 @@ xfs_iroot_realloc(/* * First copy over the btree block header. */ -memcpy (new_broot, ifp->if_broot,XFS_BTREE_LBLOCK_LEN ); +memcpy (new_broot, ifp->if_broot, +XFS_BMBT_BLOCK_LEN (ip->i_mount)); }else { new_broot =NULL ; ifp->if_flags &= ~XFS_IFBROOT ;
@@ -2114,7 +2115,7 @@ xfs_iroot_realloc( ifp->if_broot = new_broot; ifp->if_broot_bytes = (int )new_size;ASSERT (ifp->if_broot_bytes <= -XFS_IFORK_SIZE (ip, whichfork) +XFS_BROOT_SIZE_ADJ ); +XFS_IFORK_SIZE (ip, whichfork) +XFS_BROOT_SIZE_ADJ (ip));return ; }
@@ -2427,7 +2428,7 @@ xfs_iflush_fork(ASSERT (ifp->if_broot !=NULL );ASSERT (ifp->if_broot_bytes <= (XFS_IFORK_SIZE (ip, whichfork) + -XFS_BROOT_SIZE_ADJ )); +XFS_BROOT_SIZE_ADJ (ip)));xfs_bmbt_to_bmdr (mp, ifp->if_broot, ifp->if_broot_bytes, (xfs_bmdr_block_t *)cp,XFS_DFORK_SIZE (dip, mp, whichfork));
fs/xfs/xfs_log_recover.c +28 -0
@@ -29,6 +29,7 @@#include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" +#include "xfs_btree.h" #include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_inode_item.h"
@@ -1928,6 +1929,33 @@ xlog_recover_do_reg_buffer(/* Shouldn't be any more regions */ ASSERT (i == item->ri_total); + +switch (buf_f->blf_flags &XFS_BLF_TYPE_MASK ) { +case XFS_BLF_BTREE_BUF : +switch (be32_to_cpu (*(__be32 *)bp->b_addr)) { +case XFS_ABTB_CRC_MAGIC : +case XFS_ABTC_CRC_MAGIC : +case XFS_ABTB_MAGIC : +case XFS_ABTC_MAGIC : + bp->b_ops = &xfs_allocbt_buf_ops; +break ; +case XFS_IBT_CRC_MAGIC : +case XFS_IBT_MAGIC : + bp->b_ops = &xfs_inobt_buf_ops; +break ; +case XFS_BMAP_CRC_MAGIC : +case XFS_BMAP_MAGIC : + bp->b_ops = &xfs_bmbt_buf_ops; +break ; +default : +xfs_warn (mp,"Bad btree block magic!" ); +ASSERT (0 ); +break ; + } +break ; +default : +break ; + } }/*
fs/xfs/xfs_trans.h +2 -0
@@ -505,6 +505,8 @@ void xfs_trans_inode_buf(xfs_trans_t *, struct xfs_buf *);void xfs_trans_stale_inode_buf (xfs_trans_t *,struct xfs_buf *);void xfs_trans_dquot_buf (xfs_trans_t *,struct xfs_buf *,uint );void xfs_trans_inode_alloc_buf (xfs_trans_t *,struct xfs_buf *); +void xfs_trans_buf_set_type (struct xfs_trans *,struct xfs_buf *, +uint );void xfs_trans_ichgtime (struct xfs_trans *,struct xfs_inode *,int );void xfs_trans_ijoin (struct xfs_trans *,struct xfs_inode *,uint );void xfs_trans_log_buf (xfs_trans_t *,struct xfs_buf *,uint ,uint );
fs/xfs/xfs_trans_buf.c +23 -6
@@ -659,6 +659,7 @@ xfs_trans_binval(ASSERT (XFS_BUF_ISSTALE (bp));ASSERT (!(bip->bli_flags & (XFS_BLI_LOGGED |XFS_BLI_DIRTY )));ASSERT (!(bip->__bli_format.blf_flags &XFS_BLF_INODE_BUF )); +ASSERT (!(bip->__bli_format.blf_flags &XFS_BLF_TYPE_MASK ));ASSERT (bip->__bli_format.blf_flags &XFS_BLF_CANCEL );ASSERT (bip->bli_item.li_desc->lid_flags &XFS_LID_DIRTY );ASSERT (tp->t_flags &XFS_TRANS_DIRTY );
@@ -671,6 +672,7 @@ xfs_trans_binval( bip->bli_flags &= ~(XFS_BLI_INODE_BUF |XFS_BLI_LOGGED |XFS_BLI_DIRTY ); bip->__bli_format.blf_flags &= ~XFS_BLF_INODE_BUF ; bip->__bli_format.blf_flags |=XFS_BLF_CANCEL ; + bip->__bli_format.blf_flags &= ~XFS_BLF_TYPE_MASK ;for (i =0 ; i < bip->bli_format_count; i++) {memset (bip->bli_formats[i].blf_data_map,0 , (bip->bli_formats[i].blf_map_size *sizeof (uint)));
@@ -751,6 +753,26 @@ xfs_trans_inode_alloc_buf( bip->bli_flags |=XFS_BLI_INODE_ALLOC_BUF ; } +/* +* Set the type of the buffer for log recovery so that it can correctly identify +* and hence attach the correct buffer ops to the buffer after replay. +*/ +void +xfs_trans_buf_set_type ( +struct xfs_trans *tp, +struct xfs_buf *bp, +uint type) +{ +struct xfs_buf_log_item *bip = bp->b_fspriv; + +ASSERT (bp->b_transp == tp); +ASSERT (bip !=NULL ); +ASSERT (atomic_read (&bip->bli_refcount) >0 ); +ASSERT ((type &XFS_BLF_TYPE_MASK ) !=0 ); + + bip->__bli_format.blf_flags &= ~XFS_BLF_TYPE_MASK ; + bip->__bli_format.blf_flags |= type; +}/* * Similar to xfs_trans_inode_buf(), this marks the buffer as a cluster of
@@ -769,14 +791,9 @@ xfs_trans_dquot_buf( xfs_buf_t *bp, uint type) { -xfs_buf_log_item_t *bip = bp->b_fspriv; - -ASSERT (bp->b_transp == tp); -ASSERT (bip !=NULL );ASSERT (type ==XFS_BLF_UDQUOT_BUF || type ==XFS_BLF_PDQUOT_BUF || type ==XFS_BLF_GDQUOT_BUF ); -ASSERT (atomic_read (&bip->bli_refcount) >0 ); - bip->__bli_format.blf_flags |= type; +xfs_trans_buf_set_type (tp, bp, type); }
Signature · 6 lines
1.7.10.4 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
PATCH 5/21 xfs: add CRC checks to the AGF
In reply to Dave ChinnerFrom: Dave Chinner <[email protected]>
The AGF already has some self identifying fields (e.g. the sequence number) so we only need to add the uuid to it to identify the filesystem it belongs to. The location is fixed based on the sequence number, so there's no need to add a block number, either.
Hence the only additional fields are the CRC and LSN fields. These are unlogged, so place some space between the end of the logged fields and them so that future expansion of the AGF for logged fields can be placed adjacent to the existing logged fields and hence not complicate the field-derived range based logging we currently have.
Based originally on a patch from myself, modified further by Christoph Hellwig and then modified again to fit into the verifier structure with additional fields by myself. The multiple signed-off-by tags indicate the age and history of this patch.
--- fs/xfs/xfs_ag.h | 23 +++++++++++-- fs/xfs/xfs_alloc.c | 80 ++++++++++++++++++++++++++++++++-------------- fs/xfs/xfs_buf_item.h | 4 ++- fs/xfs/xfs_fsops.c | 3 ++ fs/xfs/xfs_log_recover.c | 8 +++++ 5 files changed, 91 insertions(+), 27 deletions(-)
fs/xfs/xfs_ag.h +21 -2
@@ -63,12 +63,29 @@ typedef struct xfs_agf {__be32 agf_spare0;/* spare field */ __be32 agf_levels[XFS_BTNUM_AGF ];/* btree levels */ __be32 agf_spare1;/* spare field */ +__be32 agf_flfirst;/* first freelist block's index */ __be32 agf_fllast;/* last freelist block's index */ __be32 agf_flcount;/* count of blocks in freelist */ __be32 agf_freeblks;/* total free blocks */ +__be32 agf_longest;/* longest free space */ __be32 agf_btreeblks;/* # of blocks held in AGF btrees */ +uuid_t agf_uuid;/* uuid of filesystem */ + +/* +* reserve some contiguous space for future logged fields before we add +* the unlogged fields. This makes the range logging via flags and +* structure offsets much simpler. +*/ +__be64 agf_spare64[16 ]; + +/* unlogged fields, written during buffer writeback. */ +__be64 agf_lsn;/* last write sequence */ +__be32 agf_crc;/* crc of agf sector */ +__be32 agf_spare2; + +/* structure must be padded to 64 bit alignment */ } xfs_agf_t;#define XFS_AGF_MAGICNUM 0x00000001
@@ -83,7 +100,8 @@ typedef struct xfs_agf {#define XFS_AGF_FREEBLKS 0x00000200#define XFS_AGF_LONGEST 0x00000400#define XFS_AGF_BTREEBLKS 0x00000800 -#define XFS_AGF_NUM_BITS 12 +#define XFS_AGF_UUID 0x00001000 +#define XFS_AGF_NUM_BITS 13#define XFS_AGF_ALL_BITS ((1 << XFS_AGF_NUM_BITS) - 1)#define XFS_AGF_FLAGS \
@@ -98,7 +116,8 @@ typedef struct xfs_agf { { XFS_AGF_FLCOUNT, "FLCOUNT" }, \ { XFS_AGF_FREEBLKS, "FREEBLKS" }, \ { XFS_AGF_LONGEST, "LONGEST" }, \ - { XFS_AGF_BTREEBLKS, "BTREEBLKS" } + { XFS_AGF_BTREEBLKS, "BTREEBLKS" }, \ + { XFS_AGF_UUID, "UUID" } /* disk block (xfs_daddr_t) in the AG */ #define XFS_AGF_DADDR(mp) ((xfs_daddr_t)(1 << (mp)->m_sectbb_log))
fs/xfs/xfs_alloc.c +56 -24
129 lines not on this page · raw message
fs/xfs/xfs_buf_item.h +3 -1
@@ -45,12 +45,14 @@ extern kmem_zone_t *xfs_buf_item_zone;* once the changes have been replayed into the buffer. */ #define XFS_BLF_BTREE_BUF (1<<5) +#define XFS_BLF_AGF_BUF (1<<6)#define XFS_BLF_TYPE_MASK \ (XFS_BLF_UDQUOT_BUF | \ XFS_BLF_PDQUOT_BUF | \ XFS_BLF_GDQUOT_BUF | \ - XFS_BLF_BTREE_BUF) + XFS_BLF_BTREE_BUF | \ + XFS_BLF_AGF_BUF)#define XFS_BLF_CHUNK 128#define XFS_BLF_SHIFT 7
fs/xfs/xfs_fsops.c +3 -0
@@ -247,6 +247,9 @@ xfs_growfs_data_private( tmpsize = agsize -XFS_PREALLOC_BLOCKS (mp); agf->agf_freeblks =cpu_to_be32 (tmpsize); agf->agf_longest =cpu_to_be32 (tmpsize); +if (xfs_sb_version_hascrc (&mp->m_sb)) +uuid_copy (&agf->agf_uuid, &mp->m_sb.sb_uuid); + error =xfs_bwrite (bp);xfs_buf_relse (bp);if (error)
fs/xfs/xfs_log_recover.c +8 -0
@@ -1953,6 +1953,14 @@ xlog_recover_do_reg_buffer(break ; }break ; +case XFS_BLF_AGF_BUF : +if (*(__be32 *)bp->b_addr !=cpu_to_be32 (XFS_AGF_MAGIC )) { +xfs_warn (mp,"Bad AGF block magic!" ); +ASSERT (0 ); +break ; + } + bp->b_ops = &xfs_agf_buf_ops; +break ;default :break ; }
Signature · 6 lines
1.7.10.4 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
PATCH 6/21 xfs: add CRC checks to the AGFL
In reply to Dave ChinnerFrom: Christoph Hellwig <[email protected]>
Add CRC checks, location information and a magic number to the AGFL. Previously the AGFL was just a block containing nothing but the free block pointers. The new AGFL has a real header with the usual boilerplate instead, so that we can verify it's not corrupted and written into the right place.
[[email protected]] Added LSN field, reworked significantly to fit into new verifier structure and growfs structure, enabled full verifier functionality now there is a header to verify and we can guarantee an initialised AGFL.
--- fs/xfs/xfs_ag.h | 25 +++++++++- fs/xfs/xfs_alloc.c | 119 ++++++++++++++++++++++++++++++---------------- fs/xfs/xfs_buf_item.h | 4 +- fs/xfs/xfs_fsops.c | 5 ++ fs/xfs/xfs_log_recover.c | 10 ++++ 5 files changed, 119 insertions(+), 44 deletions(-)
fs/xfs/xfs_ag.h +23 -2
@@ -30,6 +30,7 @@ struct xfs_trans;#define XFS_AGF_MAGIC 0x58414746/* 'XAGF' */ #define XFS_AGI_MAGIC 0x58414749/* 'XAGI' */ +#define XFS_AGFL_MAGIC 0x5841464c/* 'XAFL' */ #define XFS_AGF_VERSION 1#define XFS_AGI_VERSION 1
@@ -190,11 +191,31 @@ extern const struct xfs_buf_ops xfs_agi_buf_ops;*/ #define XFS_AGFL_DADDR (mp) ((xfs_daddr_t)(3 << (mp)->m_sectbb_log))#define XFS_AGFL_BLOCK (mp) XFS_HDR_BLOCK(mp, XFS_AGFL_DADDR(mp)) -#define XFS_AGFL_SIZE (mp) ((mp)->m_sb.sb_sectsize / sizeof(xfs_agblock_t))#define XFS_BUF_TO_AGFL (bp) ((xfs_agfl_t *)((bp)->b_addr)) +#define XFS_BUF_TO_AGFL_BNO (mp, bp) \ + (xfs_sb_version_hascrc(&((mp)->m_sb)) ? \ + &(XFS_BUF_TO_AGFL(bp)->agfl_bno[0]) : \ + (__be32 *)(bp)->b_addr) + +/* +* Size of the AGFL. For CRC-enabled filesystes we steal a couple of +* slots in the beginning of the block for a proper header with the +* location information and CRC. +*/ +#define XFS_AGFL_SIZE (mp) \ + (((mp)->m_sb.sb_sectsize - \ + (xfs_sb_version_hascrc(&((mp)->m_sb)) ? \ + sizeof(struct xfs_agfl) : 0)) / \ + sizeof(xfs_agblock_t)) +typedef struct xfs_agfl { -__be32 agfl_bno[1 ];/* actually XFS_AGFL_SIZE(mp) */ +__be32 agfl_magicnum; +__be32 agfl_seqno; +uuid_t agfl_uuid; +__be64 agfl_lsn; +__be32 agfl_crc; +__be32 agfl_bno[];/* actually XFS_AGFL_SIZE(mp) */ }xfs_agfl_t ;/*
fs/xfs/xfs_alloc.c +78 -41
196 lines not on this page · raw message
fs/xfs/xfs_buf_item.h +3 -1
@@ -46,13 +46,15 @@ extern kmem_zone_t *xfs_buf_item_zone;*/ #define XFS_BLF_BTREE_BUF (1<<5)#define XFS_BLF_AGF_BUF (1<<6) +#define XFS_BLF_AGFL_BUF (1<<7)#define XFS_BLF_TYPE_MASK \ (XFS_BLF_UDQUOT_BUF | \ XFS_BLF_PDQUOT_BUF | \ XFS_BLF_GDQUOT_BUF | \ XFS_BLF_BTREE_BUF | \ - XFS_BLF_AGF_BUF) + XFS_BLF_AGF_BUF | \ + XFS_BLF_AGFL_BUF)#define XFS_BLF_CHUNK 128#define XFS_BLF_SHIFT 7
fs/xfs/xfs_fsops.c +5 -0
@@ -268,6 +268,11 @@ xfs_growfs_data_private( } agfl =XFS_BUF_TO_AGFL (bp); +if (xfs_sb_version_hascrc (&mp->m_sb)) { + agfl->agfl_magicnum =cpu_to_be32 (XFS_AGFL_MAGIC ); + agfl->agfl_seqno =cpu_to_be32 (agno); +uuid_copy (&agfl->agfl_uuid, &mp->m_sb.sb_uuid); + }for (bucket =0 ; bucket <XFS_AGFL_SIZE (mp); bucket++) agfl->agfl_bno[bucket] =cpu_to_be32 (NULLAGBLOCK );
fs/xfs/xfs_log_recover.c +10 -0
@@ -1961,6 +1961,16 @@ xlog_recover_do_reg_buffer( } bp->b_ops = &xfs_agf_buf_ops;break ; +case XFS_BLF_AGFL_BUF : +if (!xfs_sb_version_hascrc (&mp->m_sb)) +break ; +if (*(__be32 *)bp->b_addr !=cpu_to_be32 (XFS_AGFL_MAGIC )) { +xfs_warn (mp,"Bad AGFL block magic!" ); +ASSERT (0 ); +break ; + } + bp->b_ops = &xfs_agfl_buf_ops; +break ;default :break ; }
Signature · 6 lines
1.7.10.4 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
PATCH 7/21 xfs: add CRC checks to the AGI
In reply to Dave ChinnerFrom: Dave Chinner <[email protected]>
Same set of changes made to the AGF need to be made to the AGI. This patch has a similar history to the AGF, hence a similar sign-off chain.
--- fs/xfs/xfs_ag.h | 8 +++++++ fs/xfs/xfs_buf_item.h | 4 +++- fs/xfs/xfs_fsops.c | 3 +++ fs/xfs/xfs_ialloc.c | 57 ++++++++++++++++++++++++++++++++++------------ fs/xfs/xfs_log_recover.c | 8 +++++++ 5 files changed, 65 insertions(+), 15 deletions(-)
fs/xfs/xfs_ag.h +8 -0
@@ -152,6 +152,7 @@ typedef struct xfs_agi {__be32 agi_root;/* root of inode btree */ __be32 agi_level;/* levels in inode btree */ __be32 agi_freecount;/* number of free inodes */ +__be32 agi_newino;/* new inode just allocated */ __be32 agi_dirino;/* last directory inode chunk */ /*
@@ -159,6 +160,13 @@ typedef struct xfs_agi {* still being referenced. */ __be32 agi_unlinked[XFS_AGI_UNLINKED_BUCKETS ]; + +uuid_t agi_uuid;/* uuid of filesystem */ +__be32 agi_crc;/* crc of agi sector */ +__be32 agi_pad32; +__be64 agi_lsn;/* last write sequence */ + +/* structure must be padded to 64 bit alignment */ } xfs_agi_t;#define XFS_AGI_MAGICNUM 0x00000001
fs/xfs/xfs_buf_item.h +3 -1
@@ -47,6 +47,7 @@ extern kmem_zone_t *xfs_buf_item_zone;#define XFS_BLF_BTREE_BUF (1<<5)#define XFS_BLF_AGF_BUF (1<<6)#define XFS_BLF_AGFL_BUF (1<<7) +#define XFS_BLF_AGI_BUF (1<<8)#define XFS_BLF_TYPE_MASK \ (XFS_BLF_UDQUOT_BUF | \
@@ -54,7 +55,8 @@ extern kmem_zone_t *xfs_buf_item_zone; XFS_BLF_GDQUOT_BUF | \ XFS_BLF_BTREE_BUF | \ XFS_BLF_AGF_BUF | \ - XFS_BLF_AGFL_BUF) + XFS_BLF_AGFL_BUF | \ + XFS_BLF_AGI_BUF)#define XFS_BLF_CHUNK 128#define XFS_BLF_SHIFT 7
fs/xfs/xfs_fsops.c +3 -0
@@ -304,8 +304,11 @@ xfs_growfs_data_private( agi->agi_freecount =0 ; agi->agi_newino =cpu_to_be32 (NULLAGINO ); agi->agi_dirino =cpu_to_be32 (NULLAGINO ); +if (xfs_sb_version_hascrc (&mp->m_sb)) +uuid_copy (&agi->agi_uuid, &mp->m_sb.sb_uuid);for (bucket =0 ; bucket <XFS_AGI_UNLINKED_BUCKETS ; bucket++) agi->agi_unlinked[bucket] =cpu_to_be32 (NULLAGINO ); + error =xfs_bwrite (bp);xfs_buf_relse (bp);if (error)
fs/xfs/xfs_ialloc.c +43 -14
104 lines not on this page · raw message
fs/xfs/xfs_log_recover.c +8 -0
@@ -1971,6 +1971,14 @@ xlog_recover_do_reg_buffer( } bp->b_ops = &xfs_agfl_buf_ops;break ; +case XFS_BLF_AGI_BUF : +if (*(__be32 *)bp->b_addr !=cpu_to_be32 (XFS_AGI_MAGIC )) { +xfs_warn (mp,"Bad AGI block magic!" ); +ASSERT (0 ); +break ; + } + bp->b_ops = &xfs_agi_buf_ops; +break ;default :break ; }
Signature · 6 lines
1.7.10.4 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
PATCH 8/21 xfs: add CRC checks for quota blocks
In reply to Dave ChinnerFrom: Christoph Hellwig <[email protected]>
Use the reserved space in struct xfs_dqblk to store a UUID and a crc for the quota blocks.
[[email protected]] Add a LSN field and update for current verifier infrastructure.
--- fs/xfs/xfs_dquot.c | 112 ++++++++++++++++++++++++++++++++++++++++------ fs/xfs/xfs_log_recover.c | 10 +++++ fs/xfs/xfs_qm.c | 23 ++++++++-- fs/xfs/xfs_qm.h | 2 + fs/xfs/xfs_quota.h | 11 ++++- 5 files changed, 141 insertions(+), 17 deletions(-)
fs/xfs/xfs_dquot.c +99 -13
@@ -36,6 +36,7 @@#include "xfs_trans_space.h" #include "xfs_trans_priv.h" #include "xfs_qm.h" +#include "xfs_cksum.h" #include "xfs_trace.h" /*
@@ -239,6 +240,8 @@ xfs_qm_init_dquot_blk( d->dd_diskdq.d_version =XFS_DQUOT_VERSION ; d->dd_diskdq.d_id =cpu_to_be32 (curid); d->dd_diskdq.d_flags = type; +if (xfs_sb_version_hascrc (&mp->m_sb)) +uuid_copy (&d->dd_uuid, &mp->m_sb.sb_uuid); } xfs_trans_dquot_buf(tp, bp,
@@ -248,25 +251,87 @@ xfs_qm_init_dquot_blk(xfs_trans_log_buf (tp, bp,0 ,BBTOB (q->qi_dqchunklen) -1 ); } -static void +STATIC void +xfs_dquot_buf_calc_crc ( +struct xfs_mount *mp, +struct xfs_buf *bp) +{ +struct xfs_dqblk *d = (struct xfs_dqblk *)bp->b_addr; +int i; + +if (!xfs_sb_version_hascrc (&mp->m_sb)) +return ; + +for (i =0 ; i < mp->m_quotainfo->qi_dqperchunk; i++, d++) { +xfs_update_cksum ((char *)d,sizeof (struct xfs_dqblk ), + offsetof(struct xfs_dqblk , dd_crc)); + } +} + +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_qm_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 ), + offsetof(struct xfs_dqblk , dd_crc))) +return false; +if (!uuid_equal (&d->dd_uuid, &mp->m_sb.sb_uuid)) +return false; + } + +return true; +} + +STATIC boolxfs_dquot_buf_verify ( +struct xfs_mount *mp,struct xfs_buf *bp) { -struct xfs_mount *mp = bp->b_target->bt_mount;struct xfs_dqblk *d = (struct xfs_dqblk *)bp->b_addr; -struct xfs_disk_dquot *ddq;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_qm_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 < mp->m_quotainfo->qi_dqperchunk; i++) { -int error; +for (i =0 ; i < ndquots; i++) { +struct xfs_disk_dquot *ddq; +int error; ddq = &d[i].dd_diskdq;
@@ -274,27 +339,37 @@ xfs_dquot_buf_verify( id =be32_to_cpu (ddq->d_id); error =xfs_qm_dqcheck (mp, ddq, id + i,0 ,XFS_QMOPT_DOWARN , -"xfs_dquot_read_verify" ); -if (error) { -XFS_CORRUPTION_ERROR (__func__,XFS_ERRLEVEL_LOW , mp, d); -xfs_buf_ioerror (bp,EFSCORRUPTED ); -break ; - } +"xfs_dquot_buf_verify" ); +if (error) +return false; } +return true; }static void xfs_dquot_buf_read_verify (struct xfs_buf *bp) { -xfs_dquot_buf_verify (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 ); + } }void xfs_dquot_buf_write_verify (struct xfs_buf *bp) { -xfs_dquot_buf_verify (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 ; + } +xfs_dquot_buf_calc_crc (mp, bp); }const struct xfs_buf_ops xfs_dquot_buf_ops = {
@@ -1035,6 +1110,17 @@ xfs_qm_dqflush( &dqp->q_logitem.qli_item.li_lsn);/* +* copy the lsn into the on-disk dquot now while we have the in memory +* dquot here. This can't be done later in the write verifier as we +* can't get access to the log item at that point in time. +*/ +if (xfs_sb_version_hascrc (&mp->m_sb)) { +struct xfs_dqblk *dqb = (struct xfs_dqblk *)ddqp; + + dqb->dd_lsn =cpu_to_be64 (dqp->q_logitem.qli_item.li_lsn); + } + +/* * Attach an iodone routine so that we can remove this dquot from the * AIL and release the flush lock once the dquot is synced to disk. */
fs/xfs/xfs_log_recover.c +10 -0
@@ -1979,6 +1979,16 @@ xlog_recover_do_reg_buffer( } bp->b_ops = &xfs_agi_buf_ops;break ; +case XFS_BLF_UDQUOT_BUF : +case XFS_BLF_PDQUOT_BUF : +case XFS_BLF_GDQUOT_BUF : +if (*(__be16 *)bp->b_addr !=cpu_to_be16 (XFS_DQUOT_MAGIC )) { +xfs_warn (mp,"Bad DQUOT block magic!" ); +ASSERT (0 ); +break ; + } + bp->b_ops = &xfs_dquot_buf_ops; +break ;default :break ; }
fs/xfs/xfs_qm.c +20 -3
@@ -617,6 +617,20 @@ xfs_qm_dqdetach( } } +int +xfs_qm_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; +} +/* * This initializes all the quota information that's kept in the * mount structure
@@ -656,9 +670,8 @@ xfs_qm_init_quotainfo(/* Precalc some constants */ qinf->qi_dqchunklen =XFS_FSB_TO_BB (mp,XFS_DQUOT_CLUSTER_SIZE_FSB ); -ASSERT (qinf->qi_dqchunklen); - qinf->qi_dqperchunk =BBTOB (qinf->qi_dqchunklen); -do_div (qinf->qi_dqperchunk,sizeof (xfs_dqblk_t)); + qinf->qi_dqperchunk =xfs_qm_calc_dquots_per_chunk (mp, + qinf->qi_dqchunklen); mp->m_qflags |= (mp->m_sb.sb_qflags &XFS_ALL_QUOTA_CHKD );
@@ -897,6 +910,10 @@ xfs_qm_dqiter_bufs(if (error)break ; +/* +* XXX(hch): need to figure out if it makes sense to validate +* the CRC here. +*/ xfs_qm_reset_dqcounts (mp, bp, firstid, type);xfs_buf_delwri_queue (bp, buffer_list);xfs_buf_relse (bp);
fs/xfs/xfs_qm.h +2 -0
@@ -75,6 +75,8 @@ typedef struct xfs_quotainfo { &((qi)->qi_gquota_tree)) +extern int xfs_qm_calc_dquots_per_chunk (struct xfs_mount *mp, +unsigned int nbblks);extern void xfs_trans_mod_dquot (xfs_trans_t *,xfs_dquot_t *,uint ,long );extern int xfs_trans_reserve_quota_bydquots (xfs_trans_t *,xfs_mount_t *,xfs_dquot_t *,xfs_dquot_t *,long ,long ,uint );
fs/xfs/xfs_quota.h +10 -1
@@ -77,7 +77,14 @@ typedef struct xfs_disk_dquot {*/ typedef struct xfs_dqblk {xfs_disk_dquot_t dd_diskdq;/* portion that lives incore as well */ -char dd_fill[32 ];/* filling for posterity */ +char dd_fill[4 ];/* filling for posterity */ + +/* +* These two are only present on filesystems with the CRC bits set. +*/ +__be32 dd_crc;/* checksum */ +__be64 dd_lsn;/* last modification in log */ +uuid_t dd_uuid;/* location information */ }xfs_dqblk_t ;/*
@@ -380,5 +387,7 @@ extern int xfs_qm_dqcheck(struct xfs_mount *, xfs_disk_dquot_t *, xfs_dqid_t, uint, uint, char *);extern int xfs_mount_reset_sbqflags (struct xfs_mount *); +extern const struct xfs_buf_ops xfs_dquot_buf_ops; +#endif /* __KERNEL__ */ #endif /* __XFS_QUOTA_H__ */
Signature · 6 lines
1.7.10.4 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
PATCH 9/21 xfs: add version 3 inode format with CRCs
In reply to Dave ChinnerFrom: Christoph Hellwig <[email protected]>
Add a new inode version with a larger core. The primary objective is to allow for a crc of the inode, and location information (uuid and ino) to verify it was written in the right place. We also extend it by:
a creation time (for Samba); a changecount (for NFSv4); a flush sequence (in LSN format for recovery); an additional inode flags field; and some additional padding.
These additional fields are not implemented yet, but already laid out in the structure.
[[email protected]] Added LSN and flags field, some factoring and rework to capture all the necessary information in the crc calculation.
--- fs/xfs/xfs_buf_item.h | 4 +- fs/xfs/xfs_dinode.h | 33 +++++++-- fs/xfs/xfs_ialloc.c | 23 +++++- fs/xfs/xfs_inode.c | 179 ++++++++++++++++++++++++++++++++-------------- fs/xfs/xfs_inode.h | 26 +++++++ fs/xfs/xfs_inode_item.c | 2 +- fs/xfs/xfs_log_recover.c | 35 +++++++-- fs/xfs/xfs_trans_buf.c | 5 +- 8 files changed, 237 insertions(+), 70 deletions(-)
fs/xfs/xfs_buf_item.h +3 -1
@@ -48,6 +48,7 @@ extern kmem_zone_t *xfs_buf_item_zone;#define XFS_BLF_AGF_BUF (1<<6)#define XFS_BLF_AGFL_BUF (1<<7)#define XFS_BLF_AGI_BUF (1<<8) +#define XFS_BLF_DINO_BUF (1<<9)#define XFS_BLF_TYPE_MASK \ (XFS_BLF_UDQUOT_BUF | \
@@ -56,7 +57,8 @@ extern kmem_zone_t *xfs_buf_item_zone; XFS_BLF_BTREE_BUF | \ XFS_BLF_AGF_BUF | \ XFS_BLF_AGFL_BUF | \ - XFS_BLF_AGI_BUF) + XFS_BLF_AGI_BUF | \ + XFS_BLF_DINO_BUF)#define XFS_BLF_CHUNK 128#define XFS_BLF_SHIFT 7
fs/xfs/xfs_dinode.h +29 -4
@@ -19,7 +19,7 @@#define __XFS_DINODE_H__#define XFS_DINODE_MAGIC 0x494e/* 'IN' */ -#define XFS_DINODE_GOOD_VERSION (v) (((v) == 1 || (v) == 2)) +#define XFS_DINODE_GOOD_VERSION (v) ((v) >= 1 && (v) <= 3) typedef struct xfs_timestamp { __be32 t_sec; /* timestamp seconds */
@@ -70,11 +70,36 @@ typedef struct xfs_dinode {/* di_next_unlinked is the only non-core field in the old dinode */ __be32 di_next_unlinked;/* agi unlinked list ptr */ -} __attribute__((packed)) xfs_dinode_t; + +/* start of the extended dinode, writable fields */ +__be32 di_crc;/* CRC of the inode */ +__be64 di_changecount;/* number of attribute changes */ +__be64 di_lsn;/* flush sequence */ +__be64 di_flags2;/* more random flags */ +__u8 di_pad2[16 ];/* more padding for future expansion */ + +/* fields only written to during inode creation */ +xfs_timestamp_t di_crtime;/* time created */ +__be64 di_ino;/* inode number */ +uuid_t di_uuid;/* UUID of the filesystem */ + +/* structure must be padded to 64 bit alignment */ +} xfs_dinode_t;#define DI_MAX_FLUSH 0xffff/* +* Size of the core inode on disk. Version 1 and 2 inodes have +* the same size, but version 3 has grown a few additional fields. +*/ +static inline uint xfs_dinode_size (int version) +{ +if (version ==3 ) +return sizeof (struct xfs_dinode ); +return offsetof(struct xfs_dinode , di_crc); +} + +/* * The 32 bit link count in the inode theoretically maxes out at UINT_MAX. * Since the pathconf interface is signed, we use 2^31 - 1 instead. * The old inode format had a 16 bit link count, so its maximum is USHRT_MAX.
@@ -105,7 +130,7 @@ typedef enum xfs_dinode_fmt {* Inode size for given fs. */ #define XFS_LITINO (mp, version) \ - ((int)(((mp)->m_sb.sb_inodesize) - sizeof(struct xfs_dinode))) + ((int)(((mp)->m_sb.sb_inodesize) - xfs_dinode_size(version)))#define XFS_BROOT_SIZE_ADJ (ip) \ (XFS_BMBT_BLOCK_LEN((ip)->i_mount) - sizeof(xfs_bmdr_block_t))
@@ -133,7 +158,7 @@ typedef enum xfs_dinode_fmt {* Return pointers to the data or attribute forks. */ #define XFS_DFORK_DPTR (dip) \ - ((char *)(dip) + sizeof(struct xfs_dinode)) + ((char *)dip + xfs_dinode_size(dip->di_version))#define XFS_DFORK_APTR (dip) \ (XFS_DFORK_DPTR(dip) + XFS_DFORK_BOFF(dip))#define XFS_DFORK_PTR (dip,w) \
fs/xfs/xfs_ialloc.c +21 -2
@@ -167,6 +167,7 @@ xfs_ialloc_inode_init(int version;int i, j;xfs_daddr_t d; +xfs_ino_t ino =0 ;/* * Loop over the new block(s), filling in the inodes.
@@ -190,8 +191,18 @@ xfs_ialloc_inode_init(* the new inode format, then use the new inode version. Otherwise * use the old version so that old kernels will continue to be * able to use the file system. +* +* For v3 inodes, we also need to write the inode number into the inode, +* so calculate the first inode number of the chunk here as +* XFS_OFFBNO_TO_AGINO() only works on filesystem block boundaries, not +* cluster boundaries and so cannot be used in the cluster buffer loop +* below. */ -if (xfs_sb_version_hasnlink (&mp->m_sb)) +if (xfs_sb_version_hascrc (&mp->m_sb)) { + version =3 ; + ino =XFS_AGINO_TO_INO (mp, agno, +XFS_OFFBNO_TO_AGINO (mp, agbno,0 )); + }else if (xfs_sb_version_hasnlink (&mp->m_sb)) version =2 ;else version =1 ;
@@ -217,13 +228,21 @@ xfs_ialloc_inode_init(xfs_buf_zero (fbuf,0 , ninodes << mp->m_sb.sb_inodelog);for (i =0 ; i < ninodes; i++) {int ioffset = i << mp->m_sb.sb_inodelog; -uint isize =sizeof (struct xfs_dinode ); +uint isize =xfs_dinode_size (version); free =xfs_make_iptr (mp, fbuf, i); free->di_magic =cpu_to_be16 (XFS_DINODE_MAGIC ); free->di_version = version; free->di_gen =cpu_to_be32 (gen); free->di_next_unlinked =cpu_to_be32 (NULLAGINO ); + +if (version ==3 ) { + free->di_ino =cpu_to_be64 (ino); + ino++; +uuid_copy (&free->di_uuid, &mp->m_sb.sb_uuid); +xfs_dinode_calc_crc (mp, free); + } +xfs_trans_log_buf (tp, fbuf, ioffset, ioffset + isize -1 ); }xfs_trans_inode_alloc_buf (tp, fbuf);
fs/xfs/xfs_inode.c +125 -54
272 lines not on this page · raw message
fs/xfs/xfs_inode.h +26 -0
@@ -150,13 +150,38 @@ typedef struct xfs_icdinode {__uint16_t di_dmstate;/* DMIG state info */ __uint16_t di_flags;/* random flags, XFS_DIFLAG_... */ __uint32_t di_gen;/* generation number */ + +/* di_next_unlinked is the only non-core field in the old dinode */ +xfs_agino_t di_next_unlinked;/* agi unlinked list ptr */ + +/* start of the extended dinode, writable fields */ +__uint32_t di_crc;/* CRC of the inode */ +__uint64_t di_changecount;/* number of attribute changes */ +xfs_lsn_t di_lsn;/* flush sequence */ +__uint64_t di_flags2;/* more random flags */ +__uint8_t di_pad2[16 ];/* more padding for future expansion */ + +/* fields only written to during inode creation */ +xfs_ictimestamp_t di_crtime;/* time created */ +xfs_ino_t di_ino;/* inode number */ +uuid_t di_uuid;/* UUID of the filesystem */ + +/* structure must be padded to 64 bit alignment */ } xfs_icdinode_t; +static inline uint xfs_icdinode_size (int version) +{ +if (version ==3 ) +return sizeof (struct xfs_icdinode ); +return offsetof(struct xfs_icdinode , di_next_unlinked); +} +/* * Flags for xfs_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 */ /* * Per-fork incore inode flags.
@@ -556,6 +581,7 @@ int xfs_imap_to_bp(struct xfs_mount *, struct xfs_trans *, 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 *);void xfs_idestroy_fork (struct xfs_inode *,int );
fs/xfs/xfs_inode_item.c +1 -1
@@ -179,7 +179,7 @@ xfs_inode_item_format( nvecs =1 ; vecp->i_addr = &ip->i_d; - vecp->i_len =sizeof (struct xfs_icdinode ); + vecp->i_len =xfs_icdinode_size (ip->i_d.di_version); vecp->i_type =XLOG_REG_TYPE_ICORE ; vecp++; nvecs++;
fs/xfs/xfs_log_recover.c +28 -7
@@ -1786,6 +1786,7 @@ xlog_recover_do_inode_buffer(xfs_agino_t *buffer_nextp;trace_xfs_log_recover_buf_inode_buf (mp->m_log, buf_f); + bp->b_ops = &xfs_inode_buf_ops; inodes_per_buf =BBTOB (bp->b_io_length) >> mp->m_sb.sb_inodelog;for (i =0 ; i < inodes_per_buf; i++) {
@@ -1930,6 +1931,9 @@ xlog_recover_do_reg_buffer(/* Shouldn't be any more regions */ ASSERT (i == item->ri_total); +/* Shouldn't be any more regions */ +ASSERT (i == item->ri_total); +switch (buf_f->blf_flags &XFS_BLF_TYPE_MASK ) {case XFS_BLF_BTREE_BUF :switch (be32_to_cpu (*(__be32 *)bp->b_addr)) {
@@ -1989,6 +1993,18 @@ xlog_recover_do_reg_buffer( } bp->b_ops = &xfs_dquot_buf_ops;break ; +case XFS_BLF_DINO_BUF : +/* +* we get here with inode allocation buffers, not buffers that +* track unlinked list changes. +*/ +if (*(__be16 *)bp->b_addr !=cpu_to_be16 (XFS_DINODE_MAGIC )) { +xfs_warn (mp,"Bad INODE block magic!" ); +ASSERT (0 ); +break ; + } + bp->b_ops = &xfs_inode_buf_ops; +break ;default :break ; }
@@ -2277,6 +2293,7 @@ xlog_recover_inode_pass2(int attr_index;uint fields;xfs_icdinode_t *dicp; +uint isize;int need_free =0 ;if (item->ri_buf[0 ].i_len ==sizeof (xfs_inode_log_format_t)) {
@@ -2302,7 +2319,7 @@ xlog_recover_inode_pass2(trace_xfs_log_recover_inode_recover (log, in_f); bp =xfs_buf_read (mp->m_ddev_targp, in_f->ilf_blkno, in_f->ilf_len,0 , -NULL ); + &xfs_inode_buf_ops);if (!bp) { error =ENOMEM ; goto error;
@@ -2413,7 +2430,8 @@ xlog_recover_inode_pass2( error =EFSCORRUPTED ; goto error; } -if (unlikely (item->ri_buf[1 ].i_len >sizeof (struct xfs_icdinode ))) { + isize =xfs_icdinode_size (dicp->di_version); +if (unlikely (item->ri_buf[1 ].i_len > isize)) {XFS_CORRUPTION_ERROR ("xlog_recover_inode_pass2(7)" ,XFS_ERRLEVEL_LOW , mp, dicp);xfs_buf_relse (bp);
@@ -2425,13 +2443,13 @@ xlog_recover_inode_pass2( }/* The core is in in-core format */ -xfs_dinode_to_disk (dip, item->ri_buf[1 ].i_addr); +xfs_dinode_to_disk (dip, dicp);/* the rest is in on-disk format */ -if (item->ri_buf[1 ].i_len >sizeof (struct xfs_icdinode )) { -memcpy ((xfs_caddr_t ) dip +sizeof (struct xfs_icdinode ), - item->ri_buf[1 ].i_addr +sizeof (struct xfs_icdinode ), - item->ri_buf[1 ].i_len -sizeof (struct xfs_icdinode )); +if (item->ri_buf[1 ].i_len > isize) { +memcpy ((char *)dip + isize, + item->ri_buf[1 ].i_addr + isize, + item->ri_buf[1 ].i_len - isize); } fields = in_f->ilf_fields;
@@ -2515,6 +2533,9 @@ xlog_recover_inode_pass2( } write_inode_buffer: +/* re-generate the checksum. */ +xfs_dinode_calc_crc (log->l_mp, dip); +ASSERT (bp->b_target->bt_mount == mp); bp->b_iodone = xlog_recover_iodone;xfs_buf_delwri_queue (bp, buffer_list);
fs/xfs/xfs_trans_buf.c +4 -1
@@ -704,12 +704,13 @@ xfs_trans_inode_buf(ASSERT (atomic_read (&bip->bli_refcount) >0 ); bip->bli_flags |=XFS_BLI_INODE_BUF ; +xfs_trans_buf_set_type (tp, bp,XFS_BLF_DINO_BUF ); }/* * This call is used to indicate that the buffer is going to * be staled and was an inode buffer. This means it gets -* special processing during unpin - where any inodes +* special processing during unpin - where any inodes * associated with the buffer should be removed from ail. * There is also special processing during recovery, * any replay of the inodes in the buffer needs to be
@@ -728,6 +729,7 @@ xfs_trans_stale_inode_buf( bip->bli_flags |=XFS_BLI_STALE_INODE ; bip->bli_item.li_cb = xfs_buf_iodone; +xfs_trans_buf_set_type (tp, bp,XFS_BLF_DINO_BUF ); }/*
@@ -751,6 +753,7 @@ xfs_trans_inode_alloc_buf(ASSERT (atomic_read (&bip->bli_refcount) >0 ); bip->bli_flags |=XFS_BLI_INODE_ALLOC_BUF ; +xfs_trans_buf_set_type (tp, bp,XFS_BLF_DINO_BUF ); }/*
Signature · 6 lines
1.7.10.4 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 09/21] xfs: add version 3 inode format with CRCs
Dave,
Quoted 12 lines · Dave Chinner
From: Christoph Hellwig <[email protected]>
Add a new inode version with a larger core. The primary objective is to allow for a crc of the inode, and location information (uuid and ino) to verify it was written in the right place. We also extend it by:
a creation time (for Samba); a changecount (for NFSv4); a flush sequence (in LSN format for recovery); an additional inode flags field; and some additional padding.
Quoted 5 lines
These additional fields are not implemented yet, but already laid out in the structure.
[[email protected]] Added LSN and flags field, some factoring and rework to capture all the necessary information in the crc calculation.
Comments and questions below.
Quoted 117 lines
Signed-off-by Christoph Hellwig <[email protected]>Signed-off-by Dave Chinner <[email protected]>--- fs/xfs/xfs_buf_item.h | 4 +- fs/xfs/xfs_dinode.h | 33 +++++++-- fs/xfs/xfs_ialloc.c | 23 +++++- fs/xfs/xfs_inode.c | 179 ++++++++++++++++++++++++++++++++-------------- fs/xfs/xfs_inode.h | 26 +++++++ fs/xfs/xfs_inode_item.c | 2 +- fs/xfs/xfs_log_recover.c | 35 +++++++-- fs/xfs/xfs_trans_buf.c | 5 +- 8 files changed, 237 insertions(+), 70 deletions(-)fs/xfs/xfs_buf_item.h +3
-1@@ -48,6 +48,7 @@ extern kmem_zone_t *xfs_buf_item_zone;#define XFS_BLF_AGF_BUF (1<<6)#define XFS_BLF_AGFL_BUF (1<<7)#define XFS_BLF_AGI_BUF (1<<8) +#define XFS_BLF_DINO_BUF (1<<9)#define XFS_BLF_TYPE_MASK \ (XFS_BLF_UDQUOT_BUF | \@@ -56,7 +57,8 @@ extern kmem_zone_t *xfs_buf_item_zone; XFS_BLF_BTREE_BUF | \ XFS_BLF_AGF_BUF | \ XFS_BLF_AGFL_BUF | \ - XFS_BLF_AGI_BUF) + XFS_BLF_AGI_BUF | \ + XFS_BLF_DINO_BUF)#define XFS_BLF_CHUNK 128#define XFS_BLF_SHIFT 7fs/xfs/xfs_dinode.h +29
-4@@ -19,7 +19,7 @@#define __XFS_DINODE_H__#define XFS_DINODE_MAGIC 0x494e/* 'IN' */ -#define XFS_DINODE_GOOD_VERSION (v) (((v) == 1 || (v) == 2)) +#define XFS_DINODE_GOOD_VERSION (v) ((v) >= 1 && (v) <= 3) typedef struct xfs_timestamp { __be32 t_sec; /* timestamp seconds */@@ -70,11 +70,36 @@ typedef struct xfs_dinode {/* di_next_unlinked is the only non-core field in the old dinode */ __be32 di_next_unlinked;/* agi unlinked list ptr */ -} __attribute__((packed)) xfs_dinode_t; + +/* start of the extended dinode, writable fields */ +__be32 di_crc;/* CRC of the inode */ +__be64 di_changecount;/* number of attribute changes */ +__be64 di_lsn;/* flush sequence */ +__be64 di_flags2;/* more random flags */ +__u8 di_pad2[16 ];/* more padding for future expansion */ + +/* fields only written to during inode creation */ +xfs_timestamp_t di_crtime;/* time created */ +__be64 di_ino;/* inode number */ +uuid_t di_uuid;/* UUID of the filesystem */ + +/* structure must be padded to 64 bit alignment */ +} xfs_dinode_t;#define DI_MAX_FLUSH 0xffff/* +* Size of the core inode on disk. Version 1 and 2 inodes have +* the same size, but version 3 has grown a few additional fields. +*/ +static inline uint xfs_dinode_size (int version) +{ +if (version ==3 ) +return sizeof (struct xfs_dinode ); +return offsetof(struct xfs_dinode , di_crc); +} + +/* * The 32 bit link count in the inode theoretically maxes out at UINT_MAX. * Since the pathconf interface is signed, we use 2^31 - 1 instead. * The old inode format had a 16 bit link count, so its maximum is USHRT_MAX. @@ -105,7 +130,7 @@ typedef enum xfs_dinode_fmt {* Inode size for given fs. */ #define XFS_LITINO (mp, version) \ - ((int)(((mp)->m_sb.sb_inodesize) - sizeof(struct xfs_dinode))) + ((int)(((mp)->m_sb.sb_inodesize) - xfs_dinode_size(version)))#define XFS_BROOT_SIZE_ADJ (ip) \ (XFS_BMBT_BLOCK_LEN((ip)->i_mount) - sizeof(xfs_bmdr_block_t))@@ -133,7 +158,7 @@ typedef enum xfs_dinode_fmt {* Return pointers to the data or attribute forks. */ #define XFS_DFORK_DPTR (dip) \ - ((char *)(dip) + sizeof(struct xfs_dinode)) + ((char *)dip + xfs_dinode_size(dip->di_version))#define XFS_DFORK_APTR (dip) \ (XFS_DFORK_DPTR(dip) + XFS_DFORK_BOFF(dip))#define XFS_DFORK_PTR (dip,w) \fs/xfs/xfs_ialloc.c +1
-0@@ -167,6 +167,7 @@ xfs_ialloc_inode_init(int version;int i, j;xfs_daddr_t d; +xfs_ino_t ino =0 ;/* * Loop over the new block(s), filling in the inodes.
fs/xfs/xfs_ialloc.c xfs_ialloc_inode_init( · line 199
Quoted 9 lines
fs/xfs/xfs_ialloc.c +6
-0@@ -190,8 +191,18 @@ xfs_ialloc_inode_init(* the new inode format, then use the new inode version. Otherwise * use the old version so that old kernels will continue to be * able to use the file system. +* +* For v3 inodes, we also need to write the inode number into the inode, +* so calculate the first inode number of the chunk here as +* XFS_OFFBNO_TO_AGINO() only works on filesystem block boundaries, not +* cluster boundaries and so cannot be used in the cluster buffer loop +* below.
I'm having some trouble understanding your comment. Maybe you can help me:
fs/xfs/xfs_ialloc.c xfs_ialloc_inode_init(
Quoted 11 lines
fs/xfs/xfs_ialloc.c +5
-1*/ -if (xfs_sb_version_hasnlink (&mp->m_sb)) +if (xfs_sb_version_hascrc (&mp->m_sb)) { + version =3 ; + ino =XFS_AGINO_TO_INO (mp, agno, +XFS_OFFBNO_TO_AGINO (mp, agbno,0 )); + }else if (xfs_sb_version_hasnlink (&mp->m_sb)) version =2 ;else version =1 ;@@ -217,13 +228,21 @@ xfs_ialloc_inode_init(
My reading of the loop here is ...
210 for (j = 0; j < nbufs; j++) {
for each inode cluster, j
211 /*
212 * Get the block.
213 */
214 d = XFS_AGB_TO_DADDR(mp, agno, agbno + (j * blks_per_cluster));
convert to disk address ( this AG, the AGBLOCK of the initial inode cluster plus
(current cluster j * blocks per cluster))
215 fbuf = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
216 mp->m_bsize * blks_per_cluster,
217 XBF_UNMAPPED);
get a buffer at that disk address of length (filesystem block size times the number of blocks per cluster)
which is the full length of the inode cluster
218 if (!fbuf)
219 return ENOMEM;
220 /*
221 * Initialize all inodes in this buffer and then log them. 222 * 223 * XXX: It would be much better if we had just one transaction 224 * to log a whole cluster of inodes instead of all the 225 * individual transactions causing a lot of log traffic. 226 */
227 fbuf->b_ops = &xfs_inode_buf_ops;
228 xfs_buf_zero(fbuf, 0, ninodes << mp->m_sb.sb_inodelog);
Zero the whole cluster, including literal areas
229 for (i = 0; i < ninodes; i++) {
for each inode, i
230 int ioffset = i << mp->m_sb.sb_inodelog; 231 uint isize = xfs_dinode_size(version);
232
233 free = xfs_make_iptr(mp, fbuf, i);
get a pointer into the buf to the beginning of i's inode core
234 free->di_magic = cpu_to_be16(XFS_DINODE_MAGIC); 235 free->di_version = version; 236 free->di_gen = cpu_to_be32(gen); 237 free->di_next_unlinked = cpu_to_be32(NULLAGINO);
initialize some important stuff
238
239 if (version == 3) {
240 free->di_ino = cpu_to_be64(ino);
241 ino++;
initialize ino on verion 3 inodes. and add one to ino for the next run of this loop.
It appears that for subsequent clusters where j > 1 this would stamp the wrong ino into the inode.
Something like this would be better:
ino = XFS_AGINO_TO_INO(mp, agno,
XFS_OFFBNO_TO_AGINO(mp, agbno + (j * blks_per_cluster), i));
free->di_ino = cpu_to_be64(ino);
Or you could calculate the agblock of the current inode cluster in the j loop,
outside of the i loop.
Quoted 10 lines
fs/xfs/xfs_ialloc.c +1
-1xfs_buf_zero (fbuf,0 , ninodes << mp->m_sb.sb_inodelog);for (i =0 ; i < ninodes; i++) {int ioffset = i << mp->m_sb.sb_inodelog; -uint isize =sizeof (struct xfs_dinode ); +uint isize =xfs_dinode_size (version); free =xfs_make_iptr (mp, fbuf, i); free->di_magic =cpu_to_be16 (XFS_DINODE_MAGIC ); free->di_version = version; free->di_gen =cpu_to_be32 (gen);
fs/xfs/xfs_ialloc.c xfs_ialloc_inode_init( · line 246
Quoted 10 lines
fs/xfs/xfs_ialloc.c +8
-0free->di_next_unlinked =cpu_to_be32 (NULLAGINO ); + +if (version ==3 ) { + free->di_ino =cpu_to_be64 (ino); + ino++; +uuid_copy (&free->di_uuid, &mp->m_sb.sb_uuid); +xfs_dinode_calc_crc (mp, free); + } +xfs_trans_log_buf (tp, fbuf, ioffset, ioffset + isize -1 );
If I have it right, it's ok not to log the literal are here (even though the crc was calculated including the literal area) because the log is protected by its own crcs and recovery will recalculate the crc. What do we have in the literal area after log replay in that case?
Quoted 368 lines
fs/xfs/xfs_ialloc.c +0
-0}xfs_trans_inode_alloc_buf (tp, fbuf);fs/xfs/xfs_inode.c +125
-54@@ -44,6 +44,7 @@#include "xfs_quota.h" #include "xfs_filestream.h" #include "xfs_vnodeops.h" +#include "xfs_cksum.h" #include "xfs_trace.h" #include "xfs_icache.h" @@ -866,6 +867,17 @@ xfs_dinode_from_disk( to->di_dmstate =be16_to_cpu (from->di_dmstate); to->di_flags =be16_to_cpu (from->di_flags); to->di_gen =be32_to_cpu (from->di_gen); + +if (to->di_version ==3 ) { + to->di_changecount =be64_to_cpu (from->di_changecount); + to->di_crtime.t_sec =be32_to_cpu (from->di_crtime.t_sec); + to->di_crtime.t_nsec =be32_to_cpu (from->di_crtime.t_nsec); + to->di_flags2 =be64_to_cpu (from->di_flags2); + 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)); +uuid_copy (&to->di_uuid, &from->di_uuid); + } }void @@ -902,6 +914,17 @@ xfs_dinode_to_disk( to->di_dmstate =cpu_to_be16 (from->di_dmstate); to->di_flags =cpu_to_be16 (from->di_flags); to->di_gen =cpu_to_be32 (from->di_gen); + +if (from->di_version ==3 ) { + to->di_changecount =cpu_to_be64 (from->di_changecount); + to->di_crtime.t_sec =cpu_to_be32 (from->di_crtime.t_sec); + to->di_crtime.t_nsec =cpu_to_be32 (from->di_crtime.t_nsec); + to->di_flags2 =cpu_to_be64 (from->di_flags2); + 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)); +uuid_copy (&to->di_uuid, &from->di_uuid); + } }STATIC uint@@ -962,6 +985,47 @@ xfs_dic2xflags( (XFS_DFORK_Q (dip) ?XFS_XFLAG_HASATTR :0 ); } +static bool +xfs_dinode_verify ( +struct xfs_mount *mp, +struct xfs_inode *ip, +struct xfs_dinode *dip) +{ +if (dip->di_magic !=cpu_to_be16 (XFS_DINODE_MAGIC )) +return false; + +/* only version 3 or greater inodes are extensively verified here */ +if (dip->di_version <3 ) +return true; + +if (!xfs_sb_version_hascrc (&mp->m_sb)) +return false; +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) +return false; +if (!uuid_equal (&dip->di_uuid, &mp->m_sb.sb_uuid)) +return false; +return true; +} + +void +xfs_dinode_calc_crc ( +struct xfs_mount *mp, +struct xfs_dinode *dip) +{ +__uint32_t crc; + +if (dip->di_version <3 ) +return ; + +ASSERT (xfs_sb_version_hascrc (&mp->m_sb)); + crc =xfs_start_cksum ((char *)dip, mp->m_sb.sb_inodesize, + offsetof(struct xfs_dinode , di_crc)); + dip->di_crc =xfs_end_cksum (crc); +} +/* * Read the disk inode attributes into the in-core inode structure. */ @@ -990,17 +1054,13 @@ xfs_iread(if (error)return error; -/* -* If we got something that isn't an inode it means someone -* (nfs or dmi) has a stale handle. -*/ -if (dip->di_magic !=cpu_to_be16 (XFS_DINODE_MAGIC )) { -#ifdef DEBUG -xfs_alert (mp, -"%s: dip->di_magic (0x%x) != XFS_DINODE_MAGIC (0x%x)" , - __func__,be16_to_cpu (dip->di_magic),XFS_DINODE_MAGIC ); -#endif /* DEBUG */ - error =XFS_ERROR (EINVAL ); +/* even unallocated inodes are verified */ +if (!xfs_dinode_verify (mp, ip, dip)) { +xfs_alert (mp,"%s: validation failed for inode %lld failed" , + __func__, ip->i_ino); + +XFS_CORRUPTION_ERROR (__func__,XFS_ERRLEVEL_LOW , mp, dip); + error =XFS_ERROR (EFSCORRUPTED ); goto out_brelse; }@@ -1022,10 +1082,20 @@ xfs_iread( goto out_brelse; } }else { +/* +* Partial initialisation of the in-core inode. Just the bits +* that xfs_ialloc won't overwrite or relies on being correct. +*/ ip->i_d.di_magic =be16_to_cpu (dip->di_magic); ip->i_d.di_version = dip->di_version; ip->i_d.di_gen =be32_to_cpu (dip->di_gen); ip->i_d.di_flushiter =be16_to_cpu (dip->di_flushiter); + +if (dip->di_version ==3 ) { + ip->i_d.di_ino =be64_to_cpu (dip->di_ino); +uuid_copy (&ip->i_d.di_uuid, &dip->di_uuid); + } +/* * Make sure to pull in the mode here as well in * case the inode is released without being used. @@ -1161,6 +1231,7 @@ xfs_ialloc( xfs_buf_t **ialloc_context, xfs_inode_t **ipp) { +struct xfs_mount *mp = tp->t_mountp;xfs_ino_t ino;xfs_inode_t *ip;uint flags;@@ -1187,7 +1258,7 @@ xfs_ialloc(* This is because we're setting fields here we need * to prevent others from looking at until we're done. */ - error =xfs_iget (tp->t_mountp, tp, ino,XFS_IGET_CREATE , + error =xfs_iget (mp, tp, ino,XFS_IGET_CREATE ,XFS_ILOCK_EXCL , &ip);if (error)return error;@@ -1208,7 +1279,7 @@ xfs_ialloc(* the inode version number now. This way we only do the conversion * here rather than here and in the flush/logging code. */ -if (xfs_sb_version_hasnlink (&tp->t_mountp->m_sb) && +if (xfs_sb_version_hasnlink (&mp->m_sb) && ip->i_d.di_version ==1 ) { ip->i_d.di_version =2 ;/* @@ -1258,6 +1329,19 @@ xfs_ialloc( ip->i_d.di_dmevmask =0 ; ip->i_d.di_dmstate =0 ; ip->i_d.di_flags =0 ; + +if (ip->i_d.di_version ==3 ) { +ASSERT (ip->i_d.di_ino == ino); +ASSERT (uuid_equal (&ip->i_d.di_uuid, &mp->m_sb.sb_uuid)); + ip->i_d.di_crc =0 ; + ip->i_d.di_changecount =1 ; + ip->i_d.di_lsn =0 ; + ip->i_d.di_flags2 =0 ; +memset (&(ip->i_d.di_pad2[0 ]),0 ,sizeof (ip->i_d.di_pad2)); + ip->i_d.di_crtime = ip->i_d.di_mtime; + } + + flags =XFS_ILOG_CORE ;switch (mode &S_IFMT ) {case S_IFIFO :@@ -2716,20 +2800,18 @@ abort_out: STATIC intxfs_iflush_int ( -xfs_inode_t *ip, -xfs_buf_t *bp) +struct xfs_inode *ip, +struct xfs_buf *bp) { -xfs_inode_log_item_t *iip; -xfs_dinode_t *dip; -xfs_mount_t *mp; +struct xfs_inode_log_item *iip = ip->i_itemp; +struct xfs_dinode *dip; +struct xfs_mount *mp = ip->i_mount;ASSERT (xfs_isilocked (ip,XFS_ILOCK_EXCL |XFS_ILOCK_SHARED ));ASSERT (xfs_isiflocked (ip));ASSERT (ip->i_d.di_format !=XFS_DINODE_FMT_BTREE || ip->i_d.di_nextents >XFS_IFORK_MAXEXT (ip,XFS_DATA_FORK )); - - iip = ip->i_itemp; - mp = ip->i_mount; +ASSERT (iip !=NULL && iip->ili_fields !=0 );/* set *dip = inode's place in the buffer */ dip = (xfs_dinode_t *)xfs_buf_offset (bp, ip->i_imap.im_boffset);@@ -2790,9 +2872,9 @@ xfs_iflush_int( }/* * bump the flush iteration count, used to detect flushes which -* postdate a log record during recovery. +* postdate a log record during recovery. This is redundant as we now +* log every change and hence this can't happen. Still, it doesn't hurt. */ - ip->i_d.di_flushiter++;/* @@ -2868,41 +2950,30 @@ xfs_iflush_int(* need the AIL lock, because it is a 64 bit value that cannot be read * atomically. */ -if (iip !=NULL && iip->ili_fields !=0 ) { - iip->ili_last_fields = iip->ili_fields; - iip->ili_fields =0 ; - iip->ili_logged =1 ; + iip->ili_last_fields = iip->ili_fields; + iip->ili_fields =0 ; + iip->ili_logged =1 ; -xfs_trans_ail_copy_lsn (mp->m_ail, &iip->ili_flush_lsn, - &iip->ili_item.li_lsn); +xfs_trans_ail_copy_lsn (mp->m_ail, &iip->ili_flush_lsn, + &iip->ili_item.li_lsn); -/* -* Attach the function xfs_iflush_done to the inode's -* buffer. This will remove the inode from the AIL -* and unlock the inode's flush lock when the inode is -* completely written to disk. -*/ -xfs_buf_attach_iodone (bp, xfs_iflush_done, &iip->ili_item); +/* +* Attach the function xfs_iflush_done to the inode's +* buffer. This will remove the inode from the AIL +* and unlock the inode's flush lock when the inode is +* completely written to disk. +*/ +xfs_buf_attach_iodone (bp, xfs_iflush_done, &iip->ili_item); -ASSERT (bp->b_fspriv !=NULL ); -ASSERT (bp->b_iodone !=NULL ); - }else { -/* -* We're flushing an inode which is not in the AIL and has -* not been logged. For this case we can immediately drop -* the inode flush lock because we can avoid the whole -* AIL state thing. It's OK to drop the flush lock now, -* because we've already locked the buffer and to do anything -* you really need both. -*/ -if (iip !=NULL ) { -ASSERT (iip->ili_logged ==0 ); -ASSERT (iip->ili_last_fields ==0 ); -ASSERT ((iip->ili_item.li_flags &XFS_LI_IN_AIL ) ==0 ); - } -xfs_ifunlock (ip); - } +/* update the lsn in the on disk inode if required */ +if (ip->i_d.di_version ==3 ) + dip->di_lsn =cpu_to_be64 (iip->ili_item.li_lsn); + +/* generate the checksum. */ +xfs_dinode_calc_crc (mp, dip); +ASSERT (bp->b_fspriv !=NULL ); +ASSERT (bp->b_iodone !=NULL );return 0 ; corrupt_out:fs/xfs/xfs_inode.h +26
-0@@ -150,13 +150,38 @@ typedef struct xfs_icdinode {__uint16_t di_dmstate;/* DMIG state info */ __uint16_t di_flags;/* random flags, XFS_DIFLAG_... */ __uint32_t di_gen;/* generation number */ + +/* di_next_unlinked is the only non-core field in the old dinode */ +xfs_agino_t di_next_unlinked;/* agi unlinked list ptr */ + +/* start of the extended dinode, writable fields */ +__uint32_t di_crc;/* CRC of the inode */ +__uint64_t di_changecount;/* number of attribute changes */ +xfs_lsn_t di_lsn;/* flush sequence */ +__uint64_t di_flags2;/* more random flags */ +__uint8_t di_pad2[16 ];/* more padding for future expansion */ + +/* fields only written to during inode creation */ +xfs_ictimestamp_t di_crtime;/* time created */ +xfs_ino_t di_ino;/* inode number */ +uuid_t di_uuid;/* UUID of the filesystem */ + +/* structure must be padded to 64 bit alignment */ } xfs_icdinode_t; +static inline uint xfs_icdinode_size (int version) +{ +if (version ==3 ) +return sizeof (struct xfs_icdinode ); +return offsetof(struct xfs_icdinode , di_next_unlinked); +} +/* * Flags for xfs_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 */ /* * Per-fork incore inode flags. @@ -556,6 +581,7 @@ int xfs_imap_to_bp(struct xfs_mount *, struct xfs_trans *, 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 *);void xfs_idestroy_fork (struct xfs_inode *,int );fs/xfs/xfs_inode_item.c +1
-1@@ -179,7 +179,7 @@ xfs_inode_item_format( nvecs =1 ; vecp->i_addr = &ip->i_d; - vecp->i_len =sizeof (struct xfs_icdinode ); + vecp->i_len =xfs_icdinode_size (ip->i_d.di_version); vecp->i_type =XLOG_REG_TYPE_ICORE ; vecp++; nvecs++;fs/xfs/xfs_log_recover.c +1
-0@@ -1786,6 +1786,7 @@ xlog_recover_do_inode_buffer(xfs_agino_t *buffer_nextp;trace_xfs_log_recover_buf_inode_buf (mp->m_log, buf_f); + bp->b_ops = &xfs_inode_buf_ops; inodes_per_buf =BBTOB (bp->b_io_length) >> mp->m_sb.sb_inodelog;for (i =0 ; i < inodes_per_buf; i++) {
fs/xfs/xfs_log_recover.c xlog_recover_do_reg_buffer( · line 1936
Quoted 6 lines
fs/xfs/xfs_log_recover.c +3
-0@@ -1930,6 +1931,9 @@ xlog_recover_do_reg_buffer(/* Shouldn't be any more regions */ ASSERT (i == item->ri_total); +/* Shouldn't be any more regions */ +ASSERT (i == item->ri_total); +
That appears to be duplicate of the assert above it.
Thanks,
Ben
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 09/21] xfs: add version 3 inode format with CRCs
Quoted 22 lines · Ben Myers
Dave,
Quoted 12 lines · Dave Chinner
From: Christoph Hellwig <[email protected]>
Add a new inode version with a larger core. The primary objective is to allow for a crc of the inode, and location information (uuid and ino) to verify it was written in the right place. We also extend it by:
a creation time (for Samba); a changecount (for NFSv4); a flush sequence (in LSN format for recovery); an additional inode flags field; and some additional padding.Quoted 5 lines
These additional fields are not implemented yet, but already laid out in the structure.
[[email protected]] Added LSN and flags field, some factoring and rework to capture all the necessary information in the crc calculation.
Comments and questions below.
...
Quoted 79 lines
fs/xfs/xfs_ialloc.c xfs_ialloc_inode_init( · line 199
Quoted 10 lines
fs/xfs/xfs_ialloc.c +6
-0@@ -190,8 +191,18 @@ xfs_ialloc_inode_init(* the new inode format, then use the new inode version. Otherwise * use the old version so that old kernels will continue to be * able to use the file system. +* +* For v3 inodes, we also need to write the inode number into the inode, +* so calculate the first inode number of the chunk here as +* XFS_OFFBNO_TO_AGINO() only works on filesystem block boundaries, not +* cluster boundaries and so cannot be used in the cluster buffer loop +* below. I'm having some trouble understanding your comment. Maybe you can help me:
fs/xfs/xfs_ialloc.c xfs_ialloc_inode_init(
Quoted 11 lines
fs/xfs/xfs_ialloc.c +5
-1*/ -if (xfs_sb_version_hasnlink (&mp->m_sb)) +if (xfs_sb_version_hascrc (&mp->m_sb)) { + version =3 ; + ino =XFS_AGINO_TO_INO (mp, agno, +XFS_OFFBNO_TO_AGINO (mp, agbno,0 )); + }else if (xfs_sb_version_hasnlink (&mp->m_sb)) version =2 ;else version =1 ;@@ -217,13 +228,21 @@ xfs_ialloc_inode_init(My reading of the loop here is ...
210 for (j = 0; j < nbufs; j++) {
for each inode cluster, j
211 /*
212 * Get the block.
213 */
214 d =XFS_AGB_TO_DADDR(mp, agno, agbno + (j * blks_per_cluster));convert to disk address ( this AG, the AGBLOCK of the initial inode cluster plus
(current cluster j * blocks per cluster))215 fbuf = xfs_trans_get_buf(tp,
mp->m_ddev_targp, d,
216mp->m_bsize*blks_per_cluster,
217XBF_UNMAPPED);get a buffer at that disk address of length (filesystem block size times the number of blocks per cluster)
which is the full length of the inode cluster
218 if (!fbuf)
219 return ENOMEM;
220 /*221 * Initialize all inodes in this buffer and then log them. 222 * 223 * XXX: It would be much better if we had just one transaction 224 * to log a whole cluster of inodes instead of all the 225 * individual transactions causing a lot of log traffic. 226 */227
fbuf->b_ops=&xfs_inode_buf_ops;
228xfs_buf_zero(fbuf, 0, ninodes << mp->m_sb.sb_inodelog);Zero the whole cluster, including literal areas
229 for (i = 0; i < ninodes; i++) {
for each inode, i
230 int ioffset = i << mp->m_sb.sb_inodelog; 231 uint isize = xfs_dinode_size(version);232
233 free =xfs_make_iptr(mp, fbuf, i);get a pointer into the buf to the beginning of i's inode core
234 free->di_magic = cpu_to_be16(XFS_DINODE_MAGIC); 235 free->di_version = version; 236 free->di_gen = cpu_to_be32(gen); 237 free->di_next_unlinked = cpu_to_be32(NULLAGINO);initialize some important stuff
Quoted 8 lines
238
239 if (version == 3) {
240free->di_ino=cpu_to_be64(ino);
241 ino++;initialize ino on verion 3 inodes. and add one to ino for the next run of this loop.
It appears that for subsequent clusters where j > 1 this would stamp the wrong
j > 0
D'oh.
-Ben
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 09/21] xfs: add version 3 inode format with CRCs
In reply to Ben MyersQuoted 22 lines · Ben Myers
Dave,
Quoted 12 lines · Dave Chinner
From: Christoph Hellwig <[email protected]>
Add a new inode version with a larger core. The primary objective is to allow for a crc of the inode, and location information (uuid and ino) to verify it was written in the right place. We also extend it by:
a creation time (for Samba); a changecount (for NFSv4); a flush sequence (in LSN format for recovery); an additional inode flags field; and some additional padding.Quoted 5 lines
These additional fields are not implemented yet, but already laid out in the structure.
[[email protected]] Added LSN and flags field, some factoring and rework to capture all the necessary information in the crc calculation.
Comments and questions below.
....
Quoted 84 lines
fs/xfs/xfs_ialloc.c xfs_ialloc_inode_init( · line 199
Quoted 10 lines
fs/xfs/xfs_ialloc.c +6
-0@@ -190,8 +191,18 @@ xfs_ialloc_inode_init(* the new inode format, then use the new inode version. Otherwise * use the old version so that old kernels will continue to be * able to use the file system. +* +* For v3 inodes, we also need to write the inode number into the inode, +* so calculate the first inode number of the chunk here as +* XFS_OFFBNO_TO_AGINO() only works on filesystem block boundaries, not +* cluster boundaries and so cannot be used in the cluster buffer loop +* below. I'm having some trouble understanding your comment. Maybe you can help me:
fs/xfs/xfs_ialloc.c xfs_ialloc_inode_init(
Quoted 11 lines
fs/xfs/xfs_ialloc.c +5
-1*/ -if (xfs_sb_version_hasnlink (&mp->m_sb)) +if (xfs_sb_version_hascrc (&mp->m_sb)) { + version =3 ; + ino =XFS_AGINO_TO_INO (mp, agno, +XFS_OFFBNO_TO_AGINO (mp, agbno,0 )); + }else if (xfs_sb_version_hasnlink (&mp->m_sb)) version =2 ;else version =1 ;@@ -217,13 +228,21 @@ xfs_ialloc_inode_init(My reading of the loop here is ...
210 for (j = 0; j < nbufs; j++) {
for each inode cluster, j
211 /*
212 * Get the block.
213 */
214 d =XFS_AGB_TO_DADDR(mp, agno, agbno + (j * blks_per_cluster));convert to disk address ( this AG, the AGBLOCK of the initial inode cluster plus
(current cluster j * blocks per cluster))215 fbuf = xfs_trans_get_buf(tp,
mp->m_ddev_targp, d,
216mp->m_bsize*blks_per_cluster,
217XBF_UNMAPPED);get a buffer at that disk address of length (filesystem block size times the number of blocks per cluster)
which is the full length of the inode cluster
218 if (!fbuf)
219 return ENOMEM;
220 /*221 * Initialize all inodes in this buffer and then log them. 222 * 223 * XXX: It would be much better if we had just one transaction 224 * to log a whole cluster of inodes instead of all the 225 * individual transactions causing a lot of log traffic. 226 */227
fbuf->b_ops=&xfs_inode_buf_ops;
228xfs_buf_zero(fbuf, 0, ninodes << mp->m_sb.sb_inodelog);Zero the whole cluster, including literal areas
229 for (i = 0; i < ninodes; i++) {
for each inode, i
230 int ioffset = i << mp->m_sb.sb_inodelog; 231 uint isize = xfs_dinode_size(version);232
233 free =xfs_make_iptr(mp, fbuf, i);get a pointer into the buf to the beginning of i's inode core
234 free->di_magic = cpu_to_be16(XFS_DINODE_MAGIC); 235 free->di_version = version; 236 free->di_gen = cpu_to_be32(gen); 237 free->di_next_unlinked = cpu_to_be32(NULLAGINO);initialize some important stuff
238
239 if (version == 3) {
240free->di_ino=cpu_to_be64(ino);
241 ino++;
Quoted 4 lines
initialize ino on verion 3 inodes. and add one to ino for the next run of this loop.
It appears that for subsequent clusters where j > 1 this would stamp the wrong ino into the inode.
If it was stamping incorrect numbers into the inodes, the verifiers would pick that up straight away. That's how I found that my initial code was wrong.
Quoted 4 lines
Something like this would be better:
ino = XFS_AGINO_TO_INO(mp, agno,XFS_OFFBNO_TO_AGINO(mp, agbno + (j * blks_per_cluster), i));
free->di_ino=cpu_to_be64(ino);
And that's exactly what my initial code did, and the verifiers pointed out that every second filesystem block in an inode cluster had incorrect inode numbers in it. Hence I changed the code to what I have now and added the comment about XFS_OFFBNO_TO_AGINO only working within a filesystem block, not across multiple filesystem blocks....
(Finding this sort of problem is one of the reasons the verifiers came first ;)
FWIW, 4k block size filesystem exercise the j > 0 path as the minimum chunk size is 16k, and the cluster size is 8k. Hence we have nbufs = 2, and we initialise 32 inodes per cluster buffer. For 512 byte inodes, we have nbufs = 4 and we initialise 16 inodes per cluster buffer.
So this code is most definitely being exercised and the output is correct as far as I can validate...
$ for i in `seq 64 1 127`; do
Quoted 2 lines
sudo
xfs_db-c "inode $i" -c "p v3.inumber"/dev/vdcdone
v3.inumber = 64
v3.inumber = 65
v3.inumber = 66
v3.inumber = 67
v3.inumber = 68
v3.inumber = 69
v3.inumber = 70
v3.inumber = 71
v3.inumber = 72
v3.inumber = 73
v3.inumber = 74
v3.inumber = 75
v3.inumber = 76
v3.inumber = 77
v3.inumber = 78
v3.inumber = 79
v3.inumber = 80
v3.inumber = 81
v3.inumber = 82
v3.inumber = 83
v3.inumber = 84
v3.inumber = 85
v3.inumber = 86
v3.inumber = 87
v3.inumber = 88
v3.inumber = 89
v3.inumber = 90
v3.inumber = 91
v3.inumber = 92
v3.inumber = 93
v3.inumber = 94
v3.inumber = 95
v3.inumber = 96
v3.inumber = 97
v3.inumber = 98
v3.inumber = 99
v3.inumber = 100
v3.inumber = 101
v3.inumber = 102
v3.inumber = 103
v3.inumber = 104
v3.inumber = 105
v3.inumber = 106
v3.inumber = 107
v3.inumber = 108
v3.inumber = 109
v3.inumber = 110
v3.inumber = 111
v3.inumber = 112
v3.inumber = 113
v3.inumber = 114
v3.inumber = 115
v3.inumber = 116
v3.inumber = 117
v3.inumber = 118
v3.inumber = 119
v3.inumber = 120
v3.inumber = 121
v3.inumber = 122
v3.inumber = 123
v3.inumber = 124
v3.inumber = 125
v3.inumber = 126
v3.inumber = 127
Quoted 16 lines
Quoted 16 lines
fs/xfs/xfs_ialloc.c +6
-1xfs_buf_zero (fbuf,0 , ninodes << mp->m_sb.sb_inodelog);for (i =0 ; i < ninodes; i++) {int ioffset = i << mp->m_sb.sb_inodelog; -uint isize =sizeof (struct xfs_dinode ); +uint isize =xfs_dinode_size (version); free =xfs_make_iptr (mp, fbuf, i); free->di_magic =cpu_to_be16 (XFS_DINODE_MAGIC ); free->di_version = version; free->di_gen =cpu_to_be32 (gen); free->di_next_unlinked =cpu_to_be32 (NULLAGINO ); + +if (version ==3 ) { + free->di_ino =cpu_to_be64 (ino); + ino++; +uuid_copy (&free->di_uuid, &mp->m_sb.sb_uuid);
Quoted 8 lines
fs/xfs/xfs_ialloc.c xfs_ialloc_inode_init( · line 246
Quoted 4 lines
fs/xfs/xfs_ialloc.c +3
-0+xfs_dinode_calc_crc (mp, free); + } +xfs_trans_log_buf (tp, fbuf, ioffset, ioffset + isize -1 );If I have it right, it's ok not to log the literal are here (even though the crc was calculated including the literal area) because the log is protected by its own crcs and recovery will recalculate the crc.
Prior to CRCs it's OK not to log the literal areas because the contents really don't matter. The entire buffer is zeroed because it's faster than zeroing individual inode cores one by one and it ensures that we can always tell a freshly allocated inode block with xfs_db because the literal areas are all zero (i.e. good for debugging). But these are conveniences, not a necessity, and hence the advantage of not logging the literal areas reduces the overhead of logging inode allocations *significantly*.
Quoted 2 lines
What do we have in the
literal area after log replay in that case?
For non-CRC inode buffers, it doesn't matter.
But you are right that it does matter for CRC enabled inode buffers as it will result in the CRC in the inode core being incorrect. I'l havea think about this - there are a couple of potential ways of solving the problem, and I need to think about them a bit first.
/me is now wondering if he should add his old "allocation create transaction" patch in here to completely avoid the need for logging inode buffers here for CRC enabled filesystems....
Quoted 16 lines
Quoted 16 lines
fs/xfs/xfs_log_recover.c +1
-0@@ -1786,6 +1786,7 @@ xlog_recover_do_inode_buffer(xfs_agino_t *buffer_nextp;trace_xfs_log_recover_buf_inode_buf (mp->m_log, buf_f); + bp->b_ops = &xfs_inode_buf_ops; inodes_per_buf =BBTOB (bp->b_io_length) >> mp->m_sb.sb_inodelog;for (i =0 ; i < inodes_per_buf; i++) {@@ -1930,6 +1931,9 @@ xlog_recover_do_reg_buffer(/* Shouldn't be any more regions */ ASSERT (i == item->ri_total);
Quoted 5 lines
fs/xfs/xfs_log_recover.c xlog_recover_do_reg_buffer( · line 1936
Quoted 3 lines
fs/xfs/xfs_log_recover.c +3
-0+/* Shouldn't be any more regions */ +ASSERT (i == item->ri_total); +That appears to be duplicate of the assert above it.
Argh. Stupid tool problem - that hunk should have given a merge failure, not applied with fuzz. I'll fix it up - a later patch probably removes it....
Cheers,
Dave.
Signature · 7 lines
Dave Chinner [email protected] _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 09/21] xfs: add version 3 inode format with CRCs
Quoted 39 lines · Dave Chinner
Quoted 17 lines · Ben Myers
Quoted 16 lines · Dave Chinner
fs/xfs/xfs_ialloc.c +6
-1xfs_buf_zero (fbuf,0 , ninodes << mp->m_sb.sb_inodelog);for (i =0 ; i < ninodes; i++) {int ioffset = i << mp->m_sb.sb_inodelog; -uint isize =sizeof (struct xfs_dinode ); +uint isize =xfs_dinode_size (version); free =xfs_make_iptr (mp, fbuf, i); free->di_magic =cpu_to_be16 (XFS_DINODE_MAGIC ); free->di_version = version; free->di_gen =cpu_to_be32 (gen); free->di_next_unlinked =cpu_to_be32 (NULLAGINO ); + +if (version ==3 ) { + free->di_ino =cpu_to_be64 (ino); + ino++; +uuid_copy (&free->di_uuid, &mp->m_sb.sb_uuid);Quoted 8 lines
fs/xfs/xfs_ialloc.c xfs_ialloc_inode_init( · line 246
Quoted 4 lines
fs/xfs/xfs_ialloc.c +3
-0+xfs_dinode_calc_crc (mp, free); + } +xfs_trans_log_buf (tp, fbuf, ioffset, ioffset + isize -1 );If I have it right, it's ok not to log the literal are here (even though the crc was calculated including the literal area) because the log is protected by its own crcs and recovery will recalculate the crc.
Prior to CRCs it's OK not to log the literal areas because the contents really don't matter. The entire buffer is zeroed because it's faster than zeroing individual inode cores one by one and it ensures that we can always tell a freshly allocated inode block with
xfs_dbbecause the literal areas are all zero (i.e. good for debugging). But these are conveniences, not a necessity, and hence the advantage of not logging the literal areas reduces the overhead of logging inode allocations *significantly*.Quoted 2 lines
What do we have in the
literal area after log replay in that case?
Quoted 6 lines
For non-CRC inode buffers, it doesn't matter.
But you are right that it does matter for CRC enabled inode buffers as it will result in the CRC in the inode core being incorrect. I'l havea think about this - there are a couple of potential ways of solving the problem, and I need to think about them a bit first.
Ben, FYI: I've taken the easy way out for this - log the entire inode buffer rather than just the inode core. The CRC means we are dependent on having all the inode logged so that seems to be the simplest way to deal with this problem overall, even though it increases the amount of metadata logged for inode creates substantially.
I'll address this potential performance issue in future with new inode create and unlink transactions that allow us to avoid logging buffers for all inode modifications. There are other good reasons for doing this as well (e.g. avoid the subtly broken special handling of physical inode buffer logging vs logical inode logging in log recovery), so I think this is best to just take the simple option here....
Cheers,
Dave.
Signature · 7 lines
Dave Chinner [email protected] _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 09/21] xfs: add version 3 inode format with CRCs
Hi Dave,
Quoted 54 lines · Dave Chinner
Quoted 39 lines · Dave Chinner
Quoted 17 lines · Ben Myers
Quoted 16 lines · Dave Chinner
fs/xfs/xfs_ialloc.c +6
-1xfs_buf_zero (fbuf,0 , ninodes << mp->m_sb.sb_inodelog);for (i =0 ; i < ninodes; i++) {int ioffset = i << mp->m_sb.sb_inodelog; -uint isize =sizeof (struct xfs_dinode ); +uint isize =xfs_dinode_size (version); free =xfs_make_iptr (mp, fbuf, i); free->di_magic =cpu_to_be16 (XFS_DINODE_MAGIC ); free->di_version = version; free->di_gen =cpu_to_be32 (gen); free->di_next_unlinked =cpu_to_be32 (NULLAGINO ); + +if (version ==3 ) { + free->di_ino =cpu_to_be64 (ino); + ino++; +uuid_copy (&free->di_uuid, &mp->m_sb.sb_uuid);Quoted 8 lines
fs/xfs/xfs_ialloc.c xfs_ialloc_inode_init( · line 246
Quoted 4 lines
fs/xfs/xfs_ialloc.c +3
-0+xfs_dinode_calc_crc (mp, free); + } +xfs_trans_log_buf (tp, fbuf, ioffset, ioffset + isize -1 );If I have it right, it's ok not to log the literal are here (even though the crc was calculated including the literal area) because the log is protected by its own crcs and recovery will recalculate the crc.
Prior to CRCs it's OK not to log the literal areas because the contents really don't matter. The entire buffer is zeroed because it's faster than zeroing individual inode cores one by one and it ensures that we can always tell a freshly allocated inode block with
xfs_dbbecause the literal areas are all zero (i.e. good for debugging). But these are conveniences, not a necessity, and hence the advantage of not logging the literal areas reduces the overhead of logging inode allocations *significantly*.Quoted 2 lines
What do we have in the
literal area after log replay in that case?Quoted 6 lines
For non-CRC inode buffers, it doesn't matter.
But you are right that it does matter for CRC enabled inode buffers as it will result in the CRC in the inode core being incorrect. I'l havea think about this - there are a couple of potential ways of solving the problem, and I need to think about them a bit first.
Ben, FYI: I've taken the easy way out for this - log the entire inode buffer rather than just the inode core. The CRC means we are dependent on having all the inode logged so that seems to be the simplest way to deal with this problem overall, even though it increases the amount of metadata logged for inode creates substantially.
Quoted 7 lines
I'll address this potential performance issue in future with new inode create and unlink transactions that allow us to avoid logging buffers for all inode modifications. There are other good reasons for doing this as well (e.g. avoid the subtly broken special handling of physical inode buffer logging vs logical inode logging in log recovery), so I think this is best to just take the simple option here....
It seems like this is a more general problem with fresh on-disk structures. When we calculate crc and log only part of a buffer we are prone to the crc being incorrect after log replay because the unlogged portions of the buffer are still undefined. They aren't the 0s we calculated crcs with.
I have a couple suggestions:
1) We could read the undefined garbage from disk before we initialize the structure and then calculate the crc. That way if we log only parts of the result the crc would still match after a crash.
2) Create a new transaction to write a known pattern over the entire buffer, then initialize the buffer with that pattern, calculate the crc, and still log only the parts of the buffer which were modified. In the non-crash case we still need to arrange for the buffer to be patterned after the log wraps, but it has the advantage of not having to log large structures just to zero them.
Other ideas?
Regards,
Ben
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 09/21] xfs: add version 3 inode format with CRCs
Quoted 65 lines · Ben Myers
Hi Dave,
Quoted 54 lines · Dave Chinner
Quoted 39 lines · Dave Chinner
Quoted 17 lines · Ben Myers
Quoted 16 lines · Dave Chinner
fs/xfs/xfs_ialloc.c +6
-1xfs_buf_zero (fbuf,0 , ninodes << mp->m_sb.sb_inodelog);for (i =0 ; i < ninodes; i++) {int ioffset = i << mp->m_sb.sb_inodelog; -uint isize =sizeof (struct xfs_dinode ); +uint isize =xfs_dinode_size (version); free =xfs_make_iptr (mp, fbuf, i); free->di_magic =cpu_to_be16 (XFS_DINODE_MAGIC ); free->di_version = version; free->di_gen =cpu_to_be32 (gen); free->di_next_unlinked =cpu_to_be32 (NULLAGINO ); + +if (version ==3 ) { + free->di_ino =cpu_to_be64 (ino); + ino++; +uuid_copy (&free->di_uuid, &mp->m_sb.sb_uuid);Quoted 8 lines
fs/xfs/xfs_ialloc.c xfs_ialloc_inode_init( · line 246
Quoted 4 lines
fs/xfs/xfs_ialloc.c +3
-0+xfs_dinode_calc_crc (mp, free); + } +xfs_trans_log_buf (tp, fbuf, ioffset, ioffset + isize -1 );If I have it right, it's ok not to log the literal are here (even though the crc was calculated including the literal area) because the log is protected by its own crcs and recovery will recalculate the crc.
Prior to CRCs it's OK not to log the literal areas because the contents really don't matter. The entire buffer is zeroed because it's faster than zeroing individual inode cores one by one and it ensures that we can always tell a freshly allocated inode block with
xfs_dbbecause the literal areas are all zero (i.e. good for debugging). But these are conveniences, not a necessity, and hence the advantage of not logging the literal areas reduces the overhead of logging inode allocations *significantly*.Quoted 2 lines
What do we have in the
literal area after log replay in that case?Quoted 6 lines
For non-CRC inode buffers, it doesn't matter.
But you are right that it does matter for CRC enabled inode buffers as it will result in the CRC in the inode core being incorrect. I'l havea think about this - there are a couple of potential ways of solving the problem, and I need to think about them a bit first.
Ben, FYI: I've taken the easy way out for this - log the entire inode buffer rather than just the inode core. The CRC means we are dependent on having all the inode logged so that seems to be the simplest way to deal with this problem overall, even though it increases the amount of metadata logged for inode creates substantially.
Quoted 7 lines
I'll address this potential performance issue in future with new inode create and unlink transactions that allow us to avoid logging buffers for all inode modifications. There are other good reasons for doing this as well (e.g. avoid the subtly broken special handling of physical inode buffer logging vs logical inode logging in log recovery), so I think this is best to just take the simple option here....
Quoted 5 lines
It seems like this is a more general problem with fresh on-disk structures. When we calculate crc and log only part of a buffer we are prone to the crc being incorrect after log replay because the unlogged portions of the buffer are still undefined. They aren't the 0s we calculated crcs with.
But it doesn't matter for all other metadata as we don't log CRC fields except in the inode/dquot at allocation. It is the exception rather than the rule.
Quoted 5 lines
I have a couple suggestions:
1) We could read the undefined garbage from disk before we initialize the structure and then calculate the crc. That way if we log only parts of the result the crc would still match after a crash.
The overhead of reading every inode cluster from disk during allocation will drop create performance by orders of magnitude. i.e. far worse in terms of performance than logging the entire buffer.
Quoted 7 lines
2) Create a new transaction to write a known pattern over the entire buffer, then initialize the buffer with that pattern, calculate the crc, and still log only the parts of the buffer which were modified. In the non-crash case we still need to arrange for the buffer to be patterned after the log wraps, but it has the advantage of not having to log large structures just to zero them.
We need to ensure we log the entire object if we are logging the CRC of the object. In this case, the initialisation and calculation of the CRC needs to be atomic, so it needs to be a single transactions. That's what logging the entire buffer does.
In all cases except inode and dquot initialisation, CRCs are not logged and so there is no concern about whether we are logging unused regions or not as the eventual CRC calculations during log recovery do not depend on the contents of unlogged regions being known. i.e. for buffer based objects, this is what happens:
get a new buffer
initialise new buffer
modify new buffer
log changed areas
changed regions get written to log
<time passes>
metadata writeback started
verify metadata
CRC+LSN calculated and inserted into buffer buffer written with CRC+LSN as unlogged changes.
So, if we crash while time is passing before metadata writeback, recovery does this:
read modifications out of log
read buffer off disk *without verification* as we can't
trust the contents at all.
write modifications into buffer
attach verifier to buffer
<time passes, other mods to the buffer are replayed>
metadata writeback started
verify metadata
CRC+LSN calculated and inserted into buffer buffer written with CRC+LSN as unlogged changes.
IOWs, for everything logged exclusively as a buffer, partial logging of intialised regions is a non-issue as CRCs are not logged and do not play a part in log recovery.
The fact is that inodes are special little snowflakes in that they are initialised physically in a buffer and then modified logically in transactions. As such, the CRC is calculated at the time of logical->physical transition in memory, not at the time of physical IO like is done for all other buffers.
Hence source of the problem here is that inodes are allocated via physical logging rather than logically, and as such we are logging the CRC internal to the inode. Hence we have to care about ensuring that we physically log the entire modified region that the CRC covers. i.e. this is a condition specific to inode and dquot initialisation, not a general problem for all metadata logged in buffers.
And seeing as I've mentioned dquots, I'll point out that xfs_qm_init_dquot_blk() doesn't do partial logging of the physical buffer used for initialisation - it just logs the entire buffer, exactly as I'm proposing to do here for inodes.
Cheers,
Dave.
Signature · 7 lines
Dave Chinner [email protected] _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 09/21] xfs: add version 3 inode format with CRCs
Hey Dave,
Quoted 76 lines · Dave Chinner
Quoted 63 lines · Ben Myers
Quoted 54 lines · Dave Chinner
Quoted 39 lines · Dave Chinner
Quoted 17 lines · Ben Myers
Quoted 16 lines · Dave Chinner
fs/xfs/xfs_ialloc.c +6
-1xfs_buf_zero (fbuf,0 , ninodes << mp->m_sb.sb_inodelog);for (i =0 ; i < ninodes; i++) {int ioffset = i << mp->m_sb.sb_inodelog; -uint isize =sizeof (struct xfs_dinode ); +uint isize =xfs_dinode_size (version); free =xfs_make_iptr (mp, fbuf, i); free->di_magic =cpu_to_be16 (XFS_DINODE_MAGIC ); free->di_version = version; free->di_gen =cpu_to_be32 (gen); free->di_next_unlinked =cpu_to_be32 (NULLAGINO ); + +if (version ==3 ) { + free->di_ino =cpu_to_be64 (ino); + ino++; +uuid_copy (&free->di_uuid, &mp->m_sb.sb_uuid);Quoted 8 lines
fs/xfs/xfs_ialloc.c xfs_ialloc_inode_init( · line 246
Quoted 4 lines
fs/xfs/xfs_ialloc.c +3
-0+xfs_dinode_calc_crc (mp, free); + } +xfs_trans_log_buf (tp, fbuf, ioffset, ioffset + isize -1 );If I have it right, it's ok not to log the literal are here (even though the crc was calculated including the literal area) because the log is protected by its own crcs and recovery will recalculate the crc.
Prior to CRCs it's OK not to log the literal areas because the contents really don't matter. The entire buffer is zeroed because it's faster than zeroing individual inode cores one by one and it ensures that we can always tell a freshly allocated inode block with
xfs_dbbecause the literal areas are all zero (i.e. good for debugging). But these are conveniences, not a necessity, and hence the advantage of not logging the literal areas reduces the overhead of logging inode allocations *significantly*.Quoted 2 lines
What do we have in the
literal area after log replay in that case?Quoted 6 lines
For non-CRC inode buffers, it doesn't matter.
But you are right that it does matter for CRC enabled inode buffers as it will result in the CRC in the inode core being incorrect. I'l havea think about this - there are a couple of potential ways of solving the problem, and I need to think about them a bit first.
Ben, FYI: I've taken the easy way out for this - log the entire inode buffer rather than just the inode core. The CRC means we are dependent on having all the inode logged so that seems to be the simplest way to deal with this problem overall, even though it increases the amount of metadata logged for inode creates substantially.
Quoted 7 lines
I'll address this potential performance issue in future with new inode create and unlink transactions that allow us to avoid logging buffers for all inode modifications. There are other good reasons for doing this as well (e.g. avoid the subtly broken special handling of physical inode buffer logging vs logical inode logging in log recovery), so I think this is best to just take the simple option here....
Quoted 5 lines
It seems like this is a more general problem with fresh on-disk structures. When we calculate crc and log only part of a buffer we are prone to the crc being incorrect after log replay because the unlogged portions of the buffer are still undefined. They aren't the 0s we calculated crcs with.
But it doesn't matter for all other metadata as we don't log CRC fields except in the inode/dquot at allocation. It is the exception rather than the rule.
Quoted 2 lines
I have a couple suggestions:
Quoted 7 lines
Quoted 3 lines
1) We could read the undefined garbage from disk before we initialize the structure and then calculate the crc. That way if we log only parts of the result the crc would still match after a crash.
The overhead of reading every inode cluster from disk during allocation will drop create performance by orders of magnitude. i.e. far worse in terms of performance than logging the entire buffer.
I didn't say it was a *good* suggestion. ;)
Quoted 10 lines
Quoted 7 lines
2) Create a new transaction to write a known pattern over the entire buffer, then initialize the buffer with that pattern, calculate the crc, and still log only the parts of the buffer which were modified. In the non-crash case we still need to arrange for the buffer to be patterned after the log wraps, but it has the advantage of not having to log large structures just to zero them.
We need to ensure we log the entire object if we are logging the CRC of the object.
We don't need to log the entire object if we can arrange for the contents of the buffer to be a known pattern after recovery and then calculate the CRC against that. It's just the initialization that is problematic. The rest of the time the contents are already cached anyway.
Quoted 2 lines
In this case, the initialisation and calculation of
the CRC needs to be atomic, so it needs to be a single transactions.
I agree that the initialisation of the block and the calculation of the crc must be in the same transaction. It would need to be a new log item type that specifies a pattern (normally zero) and a length to be written to the buffer. I used the wrong terminology, as usual.
Quoted 1 line
That's what logging the entire buffer does.
Yep. I'm just pointing out that if logging the entire structure becomes an issue we have some other options. This could be useful for other reasons too, e.g. to prevent stale data exposure after a crash.
Regards,
Ben
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 09/21] xfs: add version 3 inode format with CRCs
Quoted 28 lines · Ben Myers
Quoted 27 lines · Dave Chinner
Quoted 17 lines · Ben Myers
Quoted 8 lines · Dave Chinner
On Fri, Mar 15, 2013 at 12:11:04PM +1100, Dave Chinner wrote:
Ben, FYI: I've taken the easy way out for this - log the entire inode buffer rather than just the inode core. The CRC means we are dependent on having all the inode logged so that seems to be the simplest way to deal with this problem overall, even though it increases the amount of metadata logged for inode creates substantially.Quoted 7 lines
I'll address this potential performance issue in future with new inode create and unlink transactions that allow us to avoid logging buffers for all inode modifications. There are other good reasons for doing this as well (e.g. avoid the subtly broken special handling of physical inode buffer logging vs logical inode logging in log recovery), so I think this is best to just take the simple option here....
Quoted 5 lines
It seems like this is a more general problem with fresh on-disk structures. When we calculate crc and log only part of a buffer we are prone to the crc being incorrect after log replay because the unlogged portions of the buffer are still undefined. They aren't the 0s we calculated crcs with.
But it doesn't matter for all other metadata as we don't log CRC fields except in the inode/dquot at allocation. It is the exception rather than the rule.
.....
Quoted 8 lines
Quoted 8 lines
Quoted 7 lines
2) Create a new transaction to write a known pattern over the entire buffer, then initialize the buffer with that pattern, calculate the crc, and still log only the parts of the buffer which were modified. In the non-crash case we still need to arrange for the buffer to be patterned after the log wraps, but it has the advantage of not having to log large structures just to zero them.
Quoted 7 lines
Quoted 2 lines
We need to ensure we log the entire object if we are logging the CRC of the object.
We don't need to log the entire object if we can arrange for the contents of the buffer to be a known pattern after recovery and then calculate the CRC against that. It's just the initialization that is problematic. The rest of the time the contents are already cached anyway.
Right, but...
Quoted 8 lines
Quoted 2 lines
In this case, the initialisation and calculation of
the CRC needs to be atomic, so it needs to be a single transactions.I agree that the initialisation of the block and the calculation of the crc must be in the same transaction. It would need to be a new log item type that specifies a pattern (normally zero) and a length to be written to the buffer. I used the wrong terminology, as usual.
Quoted 4 lines
Quoted 1 line
That's what logging the entire buffer does.
Yep. I'm just pointing out that if logging the entire structure becomes an issue we have some other options.
.... to do that we need a new transaction type, new flags/fields in the xfs_buf_log_item, new handling of unlogged buffer contents that still are tracked in the AIL, new reservations, new transaction nesting as there's now 3 transactions needed for inode allocation, etc. It's pretty messy, and it doesn't replace the fact we then immediately have to relog the buffer with the initialised inode cores. It doesn't simplify log recovery, either, and that already has issues with buffer based inode allocation vs logical inode logging....
But, as I mentioned, I already have a patchset that basically does all this for inode allocation. It doesn't initialised buffers to a byte pattern - it initialises a contiguous extent to contain inodes, and introduces a "ordered buffer" that is not logged but is still tracked in the AIL to ensure that the correct behaviour occurs. That patchset has been around for a while - the original series I wrote:
$ ls -l src/kern/patches/icreate total 64 -rw------- 1 dave dave 10423 Dec 3 2009 xfs-icreate-factor-inode-stamping -rw------- 1 dave dave 12304 Dec 3 2009 xfs-icreate-item -rw------- 1 dave dave 6347 Dec 3 2009 xfs-icreate-ordered-buf-item -rw------- 1 dave dave 2679 Dec 3 2009 xfs-icreate-remove-log-di -rw------- 1 dave dave 4713 Dec 3 2009 xfs-icreate-use-xact -rw------- 1 dave dave 7924 Dec 3 2009 xfs-icreate-xact-recovery -rw------- 1 dave dave 6159 Dec 3 2009 xfs-icreate-xact-resv
That will solve the perf problem of inode initialisation and CRCs, as well as a bunch of other problems limiting inode create performance. It will also avoid having to log buffers for inode creation and hence remove all the recovery coherency problems that causes...
Quoted 2 lines
This could be useful for other reasons too, e.g. to prevent stale data exposure after a crash.
That can't actually happen as they are metadata buffers and hence the unreferenced contents of the buffers cannot escape to userspace....
Cheers,
Dave.
Signature · 7 lines
Dave Chinner [email protected] _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 09/21] xfs: add version 3 inode format with CRCs
In reply to Dave ChinnerHi Dave,
Quoted 30 lines · Dave Chinner
From: Christoph Hellwig <[email protected]>
Add a new inode version with a larger core. The primary objective is to allow for a crc of the inode, and location information (uuid and ino) to verify it was written in the right place. We also extend it by:
a creation time (for Samba); a changecount (for NFSv4); a flush sequence (in LSN format for recovery); an additional inode flags field; and some additional padding.These additional fields are not implemented yet, but already laid out in the structure.
[[email protected]] Added LSN and flags field, some factoring and rework to capture all the necessary information in the crc calculation.
Signed-off-by Christoph Hellwig <[email protected]>Signed-off-by Dave Chinner <[email protected]>--- fs/xfs/xfs_buf_item.h | 4 +- fs/xfs/xfs_dinode.h | 33 +++++++-- fs/xfs/xfs_ialloc.c | 23 +++++- fs/xfs/xfs_inode.c | 179 ++++++++++++++++++++++++++++++++-------------- fs/xfs/xfs_inode.h | 26 +++++++ fs/xfs/xfs_inode_item.c | 2 +- fs/xfs/xfs_log_recover.c | 35 +++++++-- fs/xfs/xfs_trans_buf.c | 5 +- 8 files changed, 237 insertions(+), 70 deletions(-)
...
Quoted 15 lines
fs/xfs/xfs_dinode.h +1
-1@@ -19,7 +19,7 @@#define __XFS_DINODE_H__#define XFS_DINODE_MAGIC 0x494e/* 'IN' */ -#define XFS_DINODE_GOOD_VERSION (v) (((v) == 1 || (v) == 2)) +#define XFS_DINODE_GOOD_VERSION (v) ((v) >= 1 && (v) <= 3) typedef struct xfs_timestamp { __be32 t_sec; /* timestamp seconds */@@ -70,11 +70,36 @@ typedef struct xfs_dinode {
fs/xfs/xfs_dinode.h typedef struct xfs_dinode { · line 79
Quoted 10 lines
fs/xfs/xfs_dinode.h +7
-1/* di_next_unlinked is the only non-core field in the old dinode */ __be32 di_next_unlinked;/* agi unlinked list ptr */ -} __attribute__((packed)) xfs_dinode_t; + +/* start of the extended dinode, writable fields */ +__be32 di_crc;/* CRC of the inode */ +__be64 di_changecount;/* number of attribute changes */ +__be64 di_lsn;/* flush sequence */ +__be64 di_flags2;/* more random flags */ +__u8 di_pad2[16 ];/* more padding for future expansion */
Please add to the pad:
(as an optimisation for the most common case, a single link) 8 bytes for a parent inode pointer
4 bytes for a name offset in the parent's data fork
and
4 bytes for an allocation policy
Thanks,
Ben
fs/xfs/xfs_dinode.h typedef struct xfs_dinode { · line 87
Quoted 8 lines
fs/xfs/xfs_dinode.h +8
-0+ +/* fields only written to during inode creation */ +xfs_timestamp_t di_crtime;/* time created */ +__be64 di_ino;/* inode number */ +uuid_t di_uuid;/* UUID of the filesystem */ + +/* structure must be padded to 64 bit alignment */ +} xfs_dinode_t;
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
PATCH 10/21 xfs: add CRC checks to remote symlinks
In reply to Dave ChinnerFrom: Dave Chinner <[email protected]>
Add a header to the remote symlink block, containing location and owner information, as well as CRCs and LSN fields. This requires verifiers to be added to the remote symlink buffers for CRC enabled filesystems.
This also fixes a bug reading multiple block symlinks, where the second block overwrites the first block when copying out the link name.
--- fs/xfs/Makefile | 5 +- fs/xfs/xfs_bmap.c | 21 +- fs/xfs/xfs_buf_item.h | 4 +- fs/xfs/xfs_log_recover.c | 9 + fs/xfs/xfs_symlink.c | 719 ++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_symlink.h | 53 ++++ fs/xfs/xfs_vnodeops.c | 480 +------------------------------ 7 files changed, 797 insertions(+), 494 deletions(-) create mode 100644 fs/xfs/xfs_symlink.c create mode 100644 fs/xfs/xfs_symlink.h
fs/xfs/Makefile +3 -2
@@ -45,11 +45,11 @@ xfs-y += xfs_aops.o \ xfs_itable.o \ xfs_message.o \ xfs_mru_cache.o \ - xfs_super.o \ - xfs_xattr.o \ xfs_rename.o \ + xfs_super.o \ xfs_utils.o \ xfs_vnodeops.o \ + xfs_xattr.o \ kmem.o \ uuid.o
@@ -73,6 +73,7 @@ xfs-y += xfs_alloc.o \ xfs_inode.o \ xfs_log_recover.o \ xfs_mount.o \ + xfs_symlink.o \ xfs_trans.o # low-level transaction/log code
fs/xfs/xfs_bmap.c +6 -15
@@ -47,6 +47,7 @@#include "xfs_filestream.h" #include "xfs_vnodeops.h" #include "xfs_trace.h" +#include "xfs_symlink.h" kmem_zone_t *xfs_bmap_free_item_zone;
@@ -1321,9 +1322,10 @@ xfs_bmap_add_attrfork_extents( }/* -* Block initialisation functions for local to extent format conversion. -* As these get more complex, they will be moved to the relevant files, -* but for now they are too simple to worry about. +* Block initialisation function for local to extent format conversion. +* +* This shouldn't actually be called by anyone, so make sure debug kernels cause +* a noticable failure. */ STATIC void xfs_bmap_local_to_extents_init_fn(
@@ -1332,23 +1334,12 @@ xfs_bmap_local_to_extents_init_fn(struct xfs_inode *ip, struct xfs_ifork *ifp) { + ASSERT(0); bp->b_ops = &xfs_bmbt_buf_ops;memcpy (bp->b_addr, ifp->if_u1.if_data, ifp->if_bytes);xfs_trans_buf_set_type (tp, bp,XFS_BLF_BTREE_BUF ); } -STATIC void -xfs_symlink_local_to_remote ( -struct xfs_trans *tp, -struct xfs_buf *bp, -struct xfs_inode *ip, -struct xfs_ifork *ifp) -{ -/* remote symlink blocks are not verifiable until CRCs come along */ - bp->b_ops =NULL ; -memcpy (bp->b_addr, ifp->if_u1.if_data, ifp->if_bytes); -} -/* * Called from xfs_bmap_add_attrfork to handle local format files. Each * different data fork content type needs a different callout to do the
fs/xfs/xfs_buf_item.h +3 -1
@@ -49,6 +49,7 @@ extern kmem_zone_t *xfs_buf_item_zone;#define XFS_BLF_AGFL_BUF (1<<7)#define XFS_BLF_AGI_BUF (1<<8)#define XFS_BLF_DINO_BUF (1<<9) +#define XFS_BLF_SYMLINK_BUF (1<<10)#define XFS_BLF_TYPE_MASK \ (XFS_BLF_UDQUOT_BUF | \
@@ -58,7 +59,8 @@ extern kmem_zone_t *xfs_buf_item_zone; XFS_BLF_AGF_BUF | \ XFS_BLF_AGFL_BUF | \ XFS_BLF_AGI_BUF | \ - XFS_BLF_DINO_BUF) + XFS_BLF_DINO_BUF | \ + XFS_BLF_SYMLINK_BUF)#define XFS_BLF_CHUNK 128#define XFS_BLF_SHIFT 7
fs/xfs/xfs_log_recover.c +9 -0
@@ -45,6 +45,7 @@#include "xfs_cksum.h" #include "xfs_trace.h" #include "xfs_icache.h" +#include "xfs_symlink.h" STATIC int xlog_find_zeroed(
@@ -2005,6 +2006,14 @@ xlog_recover_do_reg_buffer( } bp->b_ops = &xfs_inode_buf_ops;break ; +case XFS_BLF_SYMLINK_BUF : +if (*(__be32 *)bp->b_addr !=cpu_to_be32 (XFS_SYMLINK_MAGIC )) { +xfs_warn (mp,"Bad symlink block magic!" ); +ASSERT (0 ); +break ; + } + bp->b_ops = &xfs_symlink_buf_ops; +break ;default :break ; }
fs/xfs/xfs_symlink.c new file +719 -0
719 lines not on this page · raw message
fs/xfs/xfs_symlink.h new file +53 -0
53 lines not on this page · raw message
fs/xfs/xfs_vnodeops.c +4 -476
504 lines not on this page · raw message
Signature · 6 lines
1.7.10.4 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 10/21] xfs: add CRC checks to remote symlinks
Hi Dave,
Quoted 9 lines · Dave Chinner
From: Dave Chinner <[email protected]>
Add a header to the remote symlink block, containing location and owner information, as well as CRCs and LSN fields. This requires verifiers to be added to the remote symlink buffers for CRC enabled filesystems.
This also fixes a bug reading multiple block symlinks, where the second block overwrites the first block when copying out the link name.
Huh. This commit message doesn't say anything about moving symlink related code from xfs_vnodeops.c to a new file xfs_symlink.c. If you're going to cut and paste code en masse from one file to the next, that's perfectly fine with me. But please do that in a separate patch than the code you're adding for a feature so that I can focus on the new code in the review.
Looks like you need to add a GPL notice.
Thanks,
Ben
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 10/21] xfs: add CRC checks to remote symlinks
Quoted 10 lines · Ben Myers
Hi Dave,
Quoted 7 lines · Dave Chinner
From: Dave Chinner <[email protected]>
Add a header to the remote symlink block, containing location and owner information, as well as CRCs and LSN fields. This requires verifiers to be added to the remote symlink buffers for CRC enabled filesystems.
Quoted 5 lines
Quoted 2 lines
This also fixes a bug reading multiple block symlinks, where the second block overwrites the first block when copying out the link name.
Huh. This commit message doesn't say anything about moving symlink related code from
xfs_vnodeops.cto a new filexfs_symlink.c.
I'm sure I added it at one point. Maybe I lost it when folding and splitting various patches as I originally wrote this code in the userspace libxfs tree...
I'll split it back out.
Quoted 6 lines
If you're going to cut
and paste code en masse from one file to the next, that's perfectly fine with me. But please do that in a separate patch than the code you're adding for a feature so that I can focus on the new code in the review.Looks like you need to add a GPL notice.
It isn't actually necessary. All code in the kernel is covered by the GPLv2, and so notices on individual files are not technically necessary. Just because it isn't explicitly stated in the file, it doesn't mean the GPL does not apply to the code - the kernel is licensed according to what is in the COPYING file (i.e. the full GPLv2 license w/ clarifications noted by Linus), and so that is the license that applies to the new file. All that actually matters in individual files is the copyright statements themselves...
But, seeing as you are concerned, I'll add the boiler plates.
Cheers,
Dave.
Signature · 7 lines
Dave Chinner [email protected] _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 10/21] xfs: add CRC checks to remote symlinks
Hi Dave,
Quoted 14 lines · Dave Chinner
Quoted 13 lines · Ben Myers
Hi Dave,
Quoted 9 lines · Dave Chinner
From: Dave Chinner <[email protected]>
Add a header to the remote symlink block, containing location and owner information, as well as CRCs and LSN fields. This requires verifiers to be added to the remote symlink buffers for CRC enabled filesystems.
This also fixes a bug reading multiple block symlinks, where the second block overwrites the first block when copying out the link name.
Quoted 8 lines
Quoted 2 lines
Huh. This commit message doesn't say anything about moving symlink related code from
xfs_vnodeops.cto a new filexfs_symlink.c.I'm sure I added it at one point. Maybe I lost it when folding and splitting various patches as I originally wrote this code in the userspace libxfs tree...
I'll split it back out.
Much appreciated.
Quoted 7 lines
Quoted 6 lines
If you're going to cut
and paste code en masse from one file to the next, that's perfectly fine with me. But please do that in a separate patch than the code you're adding for a feature so that I can focus on the new code in the review.Looks like you need to add a GPL notice.
Quoted 8 lines
It isn't actually necessary. All code in the kernel is covered by the GPLv2, and so notices on individual files are not technically necessary. Just because it isn't explicitly stated in the file, it doesn't mean the GPL does not apply to the code - the kernel is licensed according to what is in the COPYING file (i.e. the full GPLv2 license w/ clarifications noted by Linus), and so that is the license that applies to the new file. All that actually matters in individual files is the copyright statements themselves...
IANAL. ;)
Quoted 1 line
But, seeing as you are concerned, I'll add the boiler plates.
Thanks. It appears this will sync into libxfs eventually and we've been trying to make sure the boilerplate is in place in xfsprogs.
Regards,
Ben
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 10/21] xfs: add CRC checks to remote symlinks
In reply to Dave ChinnerQuoted 9 lines · Dave Chinner
From: Dave Chinner <[email protected]>
Add a header to the remote symlink block, containing location and owner information, as well as CRCs and LSN fields. This requires verifiers to be added to the remote symlink buffers for CRC enabled filesystems.
This also fixes a bug reading multiple block symlinks, where the second block overwrites the first block when copying out the link name.
More comments below.
Quoted 52 lines
Signed-off-by Dave Chinner <[email protected]>--- fs/xfs/Makefile | 5 +- fs/xfs/xfs_bmap.c | 21 +- fs/xfs/xfs_buf_item.h | 4 +- fs/xfs/xfs_log_recover.c | 9 + fs/xfs/xfs_symlink.c | 719 ++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_symlink.h | 53 ++++ fs/xfs/xfs_vnodeops.c | 480 +------------------------------ 7 files changed, 797 insertions(+), 494 deletions(-) create mode 100644 fs/xfs/xfs_symlink.c create mode 100644 fs/xfs/xfs_symlink.hfs/xfs/Makefile +3
-2@@ -45,11 +45,11 @@ xfs-y += xfs_aops.o \ xfs_itable.o \ xfs_message.o \ xfs_mru_cache.o \ - xfs_super.o \ - xfs_xattr.o \ xfs_rename.o \ + xfs_super.o \ xfs_utils.o \ xfs_vnodeops.o \ + xfs_xattr.o \ kmem.o \ uuid.o@@ -73,6 +73,7 @@ xfs-y += xfs_alloc.o \ xfs_inode.o \ xfs_log_recover.o \ xfs_mount.o \ + xfs_symlink.o \ xfs_trans.o # low-level transaction/log codefs/xfs/xfs_bmap.c +1
-0@@ -47,6 +47,7 @@#include "xfs_filestream.h" #include "xfs_vnodeops.h" #include "xfs_trace.h" +#include "xfs_symlink.h" kmem_zone_t *xfs_bmap_free_item_zone;
fs/xfs/xfs_bmap.c xfs_bmap_add_attrfork_extents( · line 1328
Quoted 10 lines
fs/xfs/xfs_bmap.c +4
-3@@ -1321,9 +1322,10 @@ xfs_bmap_add_attrfork_extents( }/* -* Block initialisation functions for local to extent format conversion. -* As these get more complex, they will be moved to the relevant files, -* but for now they are too simple to worry about. +* Block initialisation function for local to extent format conversion. +* +* This shouldn't actually be called by anyone, so make sure debug kernels cause +* a noticable failure.
That's greater than 80 columns.
fs/xfs/xfs_bmap.c xfs_bmap_local_to_extents_init_fn( · line 1337
Quoted 8 lines
fs/xfs/xfs_bmap.c +1
-0*/ STATIC void xfs_bmap_local_to_extents_init_fn(@@ -1332,23 +1334,12 @@ xfs_bmap_local_to_extents_init_fn(struct xfs_inode *ip, struct xfs_ifork *ifp) { + ASSERT(0);
That has nothing to do with crcs.
Quoted 172 lines
fs/xfs/xfs_bmap.c +0
-12bp->b_ops = &xfs_bmbt_buf_ops;memcpy (bp->b_addr, ifp->if_u1.if_data, ifp->if_bytes);xfs_trans_buf_set_type (tp, bp,XFS_BLF_BTREE_BUF ); } -STATIC void -xfs_symlink_local_to_remote ( -struct xfs_trans *tp, -struct xfs_buf *bp, -struct xfs_inode *ip, -struct xfs_ifork *ifp) -{ -/* remote symlink blocks are not verifiable until CRCs come along */ - bp->b_ops =NULL ; -memcpy (bp->b_addr, ifp->if_u1.if_data, ifp->if_bytes); -} -/* * Called from xfs_bmap_add_attrfork to handle local format files. Each * different data fork content type needs a different callout to do the fs/xfs/xfs_buf_item.h +3
-1@@ -49,6 +49,7 @@ extern kmem_zone_t *xfs_buf_item_zone;#define XFS_BLF_AGFL_BUF (1<<7)#define XFS_BLF_AGI_BUF (1<<8)#define XFS_BLF_DINO_BUF (1<<9) +#define XFS_BLF_SYMLINK_BUF (1<<10)#define XFS_BLF_TYPE_MASK \ (XFS_BLF_UDQUOT_BUF | \@@ -58,7 +59,8 @@ extern kmem_zone_t *xfs_buf_item_zone; XFS_BLF_AGF_BUF | \ XFS_BLF_AGFL_BUF | \ XFS_BLF_AGI_BUF | \ - XFS_BLF_DINO_BUF) + XFS_BLF_DINO_BUF | \ + XFS_BLF_SYMLINK_BUF)#define XFS_BLF_CHUNK 128#define XFS_BLF_SHIFT 7fs/xfs/xfs_log_recover.c +9
-0@@ -45,6 +45,7 @@#include "xfs_cksum.h" #include "xfs_trace.h" #include "xfs_icache.h" +#include "xfs_symlink.h" STATIC int xlog_find_zeroed(@@ -2005,6 +2006,14 @@ xlog_recover_do_reg_buffer( } bp->b_ops = &xfs_inode_buf_ops;break ; +case XFS_BLF_SYMLINK_BUF : +if (*(__be32 *)bp->b_addr !=cpu_to_be32 (XFS_SYMLINK_MAGIC )) { +xfs_warn (mp,"Bad symlink block magic!" ); +ASSERT (0 ); +break ; + } + bp->b_ops = &xfs_symlink_buf_ops; +break ;default :break ; }fs/xfs/xfs_symlink.c new file +97
-0@@ -0,0 +1,719 @@ +/* +* Copyright (c) 2000-2006 Silicon Graphics, Inc. +* Copyright (c) 2012-2013 Red Hat, Inc. +* All rights reserved. +*/ + +#include "xfs.h" +#include "xfs_fs.h" +#include "xfs_types.h" +#include "xfs_bit.h" +#include "xfs_log.h" +#include "xfs_trans.h" +#include "xfs_sb.h" +#include "xfs_ag.h" +#include "xfs_dir2.h" +#include "xfs_mount.h" +#include "xfs_da_btree.h" +#include "xfs_bmap_btree.h" +#include "xfs_ialloc_btree.h" +#include "xfs_dinode.h" +#include "xfs_inode.h" +#include "xfs_inode_item.h" +#include "xfs_itable.h" +#include "xfs_ialloc.h" +#include "xfs_alloc.h" +#include "xfs_bmap.h" +#include "xfs_error.h" +#include "xfs_quota.h" +#include "xfs_utils.h" +#include "xfs_trans_space.h" +#include "xfs_log_priv.h" +#include "xfs_trace.h" +#include "xfs_symlink.h" +#include "xfs_cksum.h" +#include "xfs_buf_item.h" + + +/* +* Each contiguous block has a header, so it is not just a simple pathlen +* to FSB conversion. +*/ +int +xfs_symlink_blocks ( +struct xfs_mount *mp, +int pathlen) +{ +int fsblocks =0 ; +int len = pathlen; + +do { + fsblocks++; + len -=XFS_SYMLINK_BUF_SPACE (mp, mp->m_sb.sb_blocksize); + }while (len >0 ); + +ASSERT (fsblocks <=XFS_SYMLINK_MAPS ); +return fsblocks; +} + +static int +xfs_symlink_hdr_set ( +struct xfs_mount *mp, +xfs_ino_t ino, +uint32_t offset, +uint32_t size, +struct xfs_buf *bp) +{ +struct xfs_dsymlink_hdr *dsl = bp->b_addr; + +if (!xfs_sb_version_hascrc (&mp->m_sb)) +return 0 ; + + dsl->sl_magic =cpu_to_be32 (XFS_SYMLINK_MAGIC ); + dsl->sl_offset =cpu_to_be32 (offset); + dsl->sl_bytes =cpu_to_be32 (size); +uuid_copy (&dsl->sl_uuid, &mp->m_sb.sb_uuid); + dsl->sl_owner =cpu_to_be64 (ino); + dsl->sl_blkno =cpu_to_be64 (bp->b_bn); + bp->b_ops = &xfs_symlink_buf_ops; + +return sizeof (struct xfs_dsymlink_hdr ); +} + +/* +* Checking of the symlink header is split into two parts. the verifier does +* CRC, location and bounds checking, the unpacking function checks the path +* parameters and owner. +*/ +bool +xfs_symlink_hdr_ok ( +struct xfs_mount *mp, +xfs_ino_t ino, +uint32_t offset, +uint32_t size, +struct xfs_buf *bp) +{ +struct xfs_dsymlink_hdr *dsl = bp->b_addr; +
fs/xfs/xfs_symlink.c line 107
Quoted 10 lines
fs/xfs/xfs_symlink.c new file +10
-0+if (offset !=be32_to_cpu (dsl->sl_offset)) +return false; +if (size !=be32_to_cpu (dsl->sl_bytes)) +return false; +if (ino !=be64_to_cpu (dsl->sl_owner)) +return false; + +/* ok */ +return true; +
Looks like an extra line here.
-Ben
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 10/21] xfs: add CRC checks to remote symlinks
Quoted 12 lines · Ben Myers
Quoted 9 lines · Dave Chinner
From: Dave Chinner <[email protected]>
Add a header to the remote symlink block, containing location and owner information, as well as CRCs and LSN fields. This requires verifiers to be added to the remote symlink buffers for CRC enabled filesystems.
This also fixes a bug reading multiple block symlinks, where the second block overwrites the first block when copying out the link name.
More comments below.
....
Quoted 11 lines
fs/xfs/xfs_bmap.c xfs_bmap_local_to_extents_init_fn( · line 1337
Quoted 9 lines
*/
STATIC void
xfs_bmap_local_to_extents_init_fn(fs/xfs/xfs_bmap.c +1
-0@@ -1332,23 +1334,12 @@ xfs_bmap_local_to_extents_init_fn(struct xfs_inode *ip, struct xfs_ifork *ifp) { + ASSERT(0);That has nothing to do with crcs.
It most definitely does. This path is completely invalid to take now that CRCs are enabled for remote symlink blocks.
Every caller through this function requires a transformation of opaque data to block format. For CRC enable blocks, that means a type specific handler *must* be used for header initialisation and copying the data. Hence for debug kernels we want to know immediately if this path is *ever* taken, because it is indicative of an unhandled local-to-extent format transition out of xfs_bmapi_write().
This is *exactly* the path that caused the bmbt verifier failures on remote symlink buffers in 3.8.0. Once I've had time to study the code more thoroughly, I'll probably remove the entire local-to-extents path from xfs_bmapi_write() because there should be no existing users of the path and callers should do the format transformation themselves as is done right now....
Cheers,
Dave.
Signature · 7 lines
Dave Chinner [email protected] _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
PATCH 11/21 xfs: add CRC checks to block format directory blocks
In reply to Dave ChinnerFrom: Dave Chinner <[email protected]>
Now that directory buffers are made from a single struct xfs_buf, we can add CRC calculation and checking callbacks. While there, add all the fields to the on disk structures for future functionality such as d_type support, uuids, block numbers, owner inode, etc.
To distinguish between the different on disk formats, change the magic numbers for the new format directory blocks.
--- fs/xfs/xfs_dir2_block.c | 132 +++++++++++++++++++++++++++----------- fs/xfs/xfs_dir2_data.c | 160 ++++++++++++++++++++++++++++------------------ fs/xfs/xfs_dir2_format.h | 155 ++++++++++++++++++++++++++++++++++++++++++-- fs/xfs/xfs_dir2_leaf.c | 6 +- fs/xfs/xfs_dir2_node.c | 2 +- fs/xfs/xfs_dir2_priv.h | 4 +- fs/xfs/xfs_dir2_sf.c | 2 +- fs/xfs/xfs_log_recover.c | 2 + 8 files changed, 352 insertions(+), 111 deletions(-)
fs/xfs/xfs_dir2_block.c +94 -38
@@ -1,5 +1,6 @@/* * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. +* Copyright (c) 2013 Red Hat, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or
@@ -28,11 +29,13 @@#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_inode_item.h" +#include "xfs_buf_item.h" #include "xfs_dir2.h" #include "xfs_dir2_format.h" #include "xfs_dir2_priv.h" #include "xfs_error.h" #include "xfs_trace.h" +#include "xfs_cksum.h" /* * Local function prototypes.
@@ -56,44 +59,74 @@ xfs_dir_startup(void) xfs_dir_hash_dotdot =xfs_da_hashname ((unsigned char *)".." ,2 ); } -static void -xfs_dir2_block_verify ( +static bool +xfs_dir3_block_verify (struct xfs_buf *bp) {struct xfs_mount *mp = bp->b_target->bt_mount; -struct xfs_dir2_data_hdr *hdr = bp->b_addr; -int block_ok =0 ; - - block_ok = hdr->magic ==cpu_to_be32 (XFS_DIR2_BLOCK_MAGIC ); - block_ok = block_ok &&__xfs_dir2_data_check (NULL , bp) ==0 ; - -if (!block_ok) { -XFS_CORRUPTION_ERROR (__func__,XFS_ERRLEVEL_LOW , mp, hdr); -xfs_buf_ioerror (bp,EFSCORRUPTED ); +struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; + +if (xfs_sb_version_hascrc (&mp->m_sb)) { +if (hdr3->magic !=be32_to_cpu (XFS_DIR3_BLOCK_MAGIC )) +return false; +if (!uuid_equal (&hdr3->uuid, &mp->m_sb.sb_uuid)) +return false; +if (be64_to_cpu (hdr3->blkno) != bp->b_bn) +return false; + }else { +if (hdr3->magic !=be32_to_cpu (XFS_DIR2_BLOCK_MAGIC )) +return false; } +if (__xfs_dir2_data_check (NULL , bp)) +return false; +return true; }static void -xfs_dir2_block_read_verify ( +xfs_dir3_block_read_verify (struct xfs_buf *bp) { -xfs_dir2_block_verify (bp); +struct xfs_mount *mp = bp->b_target->bt_mount; + +if ((xfs_sb_version_hascrc (&mp->m_sb) && + !xfs_verify_cksum (bp->b_addr,BBTOB (bp->b_length), +XFS_DIR3_DATA_CRC_OFF )) || + !xfs_dir3_block_verify (bp)) { +XFS_CORRUPTION_ERROR (__func__,XFS_ERRLEVEL_LOW , mp, bp->b_addr); +xfs_buf_ioerror (bp,EFSCORRUPTED ); + } }static void -xfs_dir2_block_write_verify ( +xfs_dir3_block_write_verify (struct xfs_buf *bp) { -xfs_dir2_block_verify (bp); +struct xfs_mount *mp = bp->b_target->bt_mount; +struct xfs_buf_log_item *bip = bp->b_fspriv; +struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; + +if (!xfs_dir3_block_verify (bp)) { +XFS_CORRUPTION_ERROR (__func__,XFS_ERRLEVEL_LOW , mp, bp->b_addr); +xfs_buf_ioerror (bp,EFSCORRUPTED ); +return ; + } + +if (!xfs_sb_version_hascrc (&mp->m_sb)) +return ; + +if (bip) + hdr3->lsn =cpu_to_be64 (bip->bli_item.li_lsn); + +xfs_update_cksum (bp->b_addr,BBTOB (bp->b_length),XFS_DIR3_DATA_CRC_OFF ); } -const struct xfs_buf_ops xfs_dir2_block_buf_ops = { - .verify_read = xfs_dir2_block_read_verify, - .verify_write = xfs_dir2_block_write_verify, +const struct xfs_buf_ops xfs_dir3_block_buf_ops = { + .verify_read = xfs_dir3_block_read_verify, + .verify_write = xfs_dir3_block_write_verify, };static int -xfs_dir2_block_read ( +xfs_dir3_block_read (struct xfs_trans *tp,struct xfs_inode *dp,struct xfs_buf **bpp)
@@ -101,7 +134,29 @@ xfs_dir2_block_read(struct xfs_mount *mp = dp->i_mount;return xfs_da_read_buf (tp, dp, mp->m_dirdatablk,-1 , bpp, -XFS_DATA_FORK , &xfs_dir2_block_buf_ops); +XFS_DATA_FORK , &xfs_dir3_block_buf_ops); +} + +static void +xfs_dir3_block_init ( +struct xfs_mount *mp, +struct xfs_buf *bp, +struct xfs_inode *dp) +{ +struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; + + bp->b_ops = &xfs_dir3_block_buf_ops; + +if (xfs_sb_version_hascrc (&mp->m_sb)) { +memset (hdr3,0 ,sizeof (*hdr3)); + hdr3->magic =cpu_to_be32 (XFS_DIR3_BLOCK_MAGIC ); + hdr3->blkno =cpu_to_be64 (bp->b_bn); + hdr3->owner =cpu_to_be64 (dp->i_ino); +uuid_copy (&hdr3->uuid, &mp->m_sb.sb_uuid); +return ; + + } + hdr3->magic =cpu_to_be32 (XFS_DIR2_BLOCK_MAGIC ); } static void
@@ -121,7 +176,7 @@ xfs_dir2_block_need_space(struct xfs_dir2_data_unused *enddup =NULL ; *compact =0 ; - bf = hdr->bestfree; + bf =xfs_dir3_data_bestfree_p (hdr);/* * If there are stale entries we'll use one for the leaf.
@@ -303,7 +358,7 @@ xfs_dir2_block_addname( mp = dp->i_mount;/* Read the (one and only) directory block into bp. */ - error =xfs_dir2_block_read (tp, dp, &bp); + error =xfs_dir3_block_read (tp, dp, &bp);if (error)return error;
@@ -531,7 +586,7 @@ xfs_dir2_block_getdents(if (xfs_dir2_dataptr_to_db (mp, *offset) > mp->m_dirdatablk)return 0 ; - error =xfs_dir2_block_read (NULL , dp, &bp); + error =xfs_dir3_block_read (NULL , dp, &bp);if (error)return error;
@@ -546,7 +601,7 @@ xfs_dir2_block_getdents(* Set up values for the loop. */ btp =xfs_dir2_block_tail_p (mp, hdr); - ptr = (char *)(hdr +1 ); + ptr = (char *)xfs_dir3_data_entry_p (hdr); endptr = (char *)xfs_dir2_block_leaf_p (btp);/*
@@ -711,7 +766,7 @@ xfs_dir2_block_lookup_int( tp = args->trans; mp = dp->i_mount; - error =xfs_dir2_block_read (tp, dp, &bp); + error =xfs_dir3_block_read (tp, dp, &bp);if (error)return error;
@@ -974,9 +1029,12 @@ xfs_dir2_leaf_to_block(* These will show up in the leaf bests table. */ while (dp->i_d.di_size > mp->m_dirblksize) { +int hdrsz; + + hdrsz =xfs_dir3_data_hdr_size (xfs_sb_version_hascrc (&mp->m_sb)); bestsp =xfs_dir2_leaf_bests_p (ltp);if (be16_to_cpu (bestsp[be32_to_cpu (ltp->bestcount) -1 ]) == - mp->m_dirblksize - (uint )sizeof (*hdr)) { + mp->m_dirblksize - hdrsz) {if ((error =xfs_dir2_leaf_trim_data (args, lbp, (xfs_dir2_db_t)(be32_to_cpu (ltp->bestcount) -1 ))))
@@ -1014,8 +1072,8 @@ xfs_dir2_leaf_to_block(/* * Start converting it to block form. */ - dbp->b_ops = &xfs_dir2_block_buf_ops; - hdr->magic =cpu_to_be32 (XFS_DIR2_BLOCK_MAGIC ); +xfs_dir3_block_init (mp, dbp, dp); + needlog =1 ; needscan =0 ;/*
@@ -1137,16 +1195,16 @@ xfs_dir2_sf_to_block(return error; }/* -* Initialize the data block. +* Initialize the data block, then convert it to block format. */ - error =xfs_dir2_data_init (args, blkno, &bp); + error =xfs_dir3_data_init (args, blkno, &bp);if (error) {kmem_free (sfp);return error; } - bp->b_ops = &xfs_dir2_block_buf_ops; +xfs_dir3_block_init (mp, bp, dp); hdr = bp->b_addr; - hdr->magic =cpu_to_be32 (XFS_DIR2_BLOCK_MAGIC ); +/* * Compute size of block "tail" area. */
@@ -1156,7 +1214,7 @@ xfs_dir2_sf_to_block(* The whole thing is initialized to free by the init routine. * Say we're using the leaf and tail area. */ - dup = (xfs_dir2_data_unused_t *)(hdr +1 ); + dup =xfs_dir3_data_unused_p (hdr); needlog = needscan =0 ;xfs_dir2_data_use_free (tp, bp, dup, mp->m_dirblksize - i, i, &needlog, &needscan);
@@ -1178,8 +1236,7 @@ xfs_dir2_sf_to_block(/* * Create entry for . */ - dep = (xfs_dir2_data_entry_t *) - ((char *)hdr +XFS_DIR2_DATA_DOT_OFFSET ); + dep =xfs_dir3_data_dot_entry_p (hdr); dep->inumber =cpu_to_be64 (dp->i_ino); dep->namelen =1 ; dep->name[0 ] ='.' ;
@@ -1192,8 +1249,7 @@ xfs_dir2_sf_to_block(/* * Create entry for .. */ - dep = (xfs_dir2_data_entry_t *) - ((char *)hdr +XFS_DIR2_DATA_DOTDOT_OFFSET ); + dep =xfs_dir3_data_dotdot_entry_p (hdr); dep->inumber =cpu_to_be64 (xfs_dir2_sf_get_parent_ino (sfp)); dep->namelen =2 ; dep->name[0 ] = dep->name[1 ] ='.' ;
@@ -1203,7 +1259,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_DIR2_DATA_FIRST_OFFSET ; + offset =xfs_dir3_data_first_offset (hdr);/* * Loop over existing entries, stuff them in. */
fs/xfs/xfs_dir2_data.c +99 -61
409 lines not on this page · raw message
fs/xfs/xfs_dir2_format.h +149 -6
210 lines not on this page · raw message
fs/xfs/xfs_dir2_leaf.c +4 -2
@@ -149,6 +149,7 @@ xfs_dir2_block_to_leaf(int needlog;/* need to log block header */ int needscan;/* need to rescan bestfree */ xfs_trans_t *tp;/* transaction pointer */ +struct xfs_dir2_data_free *bf;trace_xfs_dir2_block_to_leaf (args);
@@ -177,6 +178,7 @@ xfs_dir2_block_to_leaf(xfs_dir2_data_check (dp, dbp); btp =xfs_dir2_block_tail_p (mp, hdr); blp =xfs_dir2_block_leaf_p (btp); + bf =xfs_dir3_data_bestfree_p (hdr);/* * Set the counts in the leaf header. */
@@ -212,7 +214,7 @@ xfs_dir2_block_to_leaf( ltp =xfs_dir2_leaf_tail_p (mp, leaf); ltp->bestcount =cpu_to_be32 (1 ); bestsp =xfs_dir2_leaf_bests_p (ltp); - bestsp[0 ] = hdr->bestfree[0 ].length; + bestsp[0 ] = bf[0 ].length;/* * Log the data header and leaf bests table. */
@@ -544,7 +546,7 @@ xfs_dir2_leaf_addname(/* * Initialize the block. */ -if ((error =xfs_dir2_data_init (args, use_block, &dbp))) { +if ((error =xfs_dir3_data_init (args, use_block, &dbp))) {xfs_trans_brelse (tp, lbp);return error; }
fs/xfs/xfs_dir2_node.c +1 -1
@@ -1588,7 +1588,7 @@ xfs_dir2_node_addname_int(if (unlikely ((error =xfs_dir2_grow_inode (args,XFS_DIR2_DATA_SPACE , &dbno)) || - (error =xfs_dir2_data_init (args, dbno, &dbp)))) + (error =xfs_dir3_data_init (args, dbno, &dbp))))return error;/*
fs/xfs/xfs_dir2_priv.h +2 -2
@@ -30,7 +30,7 @@ extern int xfs_dir_cilookup_result(struct xfs_da_args *args, const unsigned char *name, int len);/* xfs_dir2_block.c */ -extern const struct xfs_buf_ops xfs_dir2_block_buf_ops; +extern const struct xfs_buf_ops xfs_dir3_block_buf_ops;extern int xfs_dir2_block_addname (struct xfs_da_args *args); extern int xfs_dir2_block_getdents(struct xfs_inode *dp, void *dirent,
@@ -61,7 +61,7 @@ xfs_dir2_data_freeinsert(struct xfs_dir2_data_hdr *hdr, struct xfs_dir2_data_unused *dup, int *loghead);extern void xfs_dir2_data_freescan (struct xfs_mount *mp,struct xfs_dir2_data_hdr *hdr,int *loghead); -extern int xfs_dir2_data_init (struct xfs_da_args *args,xfs_dir2_db_t blkno, +extern int xfs_dir3_data_init (struct xfs_da_args *args,xfs_dir2_db_t blkno,struct xfs_buf **bpp);extern void xfs_dir2_data_log_entry (struct xfs_trans *tp,struct xfs_buf *bp,struct xfs_dir2_data_entry *dep);
fs/xfs/xfs_dir2_sf.c +1 -1
@@ -278,7 +278,7 @@ xfs_dir2_block_to_sf(* Set up to loop over the block's entries. */ btp =xfs_dir2_block_tail_p (mp, hdr); - ptr = (char *)(hdr +1 ); + ptr = (char *)xfs_dir3_data_entry_p (hdr); endptr = (char *)xfs_dir2_block_leaf_p (btp); sfep =xfs_dir2_sf_firstentry (sfp);/*
fs/xfs/xfs_log_recover.c +2 -0
@@ -1876,6 +1876,7 @@ xlog_recover_do_reg_buffer(int bit;int nbits;int error; +struct xfs_da_blkinfo *info;trace_xfs_log_recover_buf_reg_buf (mp->m_log, buf_f);
@@ -1935,6 +1936,7 @@ xlog_recover_do_reg_buffer(/* Shouldn't be any more regions */ ASSERT (i == item->ri_total); + info = bp->b_addr;switch (buf_f->blf_flags &XFS_BLF_TYPE_MASK ) {case XFS_BLF_BTREE_BUF :switch (be32_to_cpu (*(__be32 *)bp->b_addr)) {
Signature · 6 lines
1.7.10.4 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 11/21] xfs: add CRC checks to block format directory blocks
Quoted 9 lines · Dave Chinner
From: Dave Chinner <[email protected]>
Now that directory buffers are made from a single struct
xfs_buf, we can add CRC calculation and checking callbacks. While there, add all the fields to the on disk structures for future functionality such asd_typesupport, uuids, block numbers, owner inode, etc.To distinguish between the different on disk formats, change the magic numbers for the new format directory blocks.
Comments below.
Quoted 59 lines
Signed-off-by Dave Chinner <[email protected]>--- fs/xfs/xfs_dir2_block.c | 132 +++++++++++++++++++++++++++----------- fs/xfs/xfs_dir2_data.c | 160 ++++++++++++++++++++++++++++------------------ fs/xfs/xfs_dir2_format.h | 155 ++++++++++++++++++++++++++++++++++++++++++-- fs/xfs/xfs_dir2_leaf.c | 6 +- fs/xfs/xfs_dir2_node.c | 2 +- fs/xfs/xfs_dir2_priv.h | 4 +- fs/xfs/xfs_dir2_sf.c | 2 +- fs/xfs/xfs_log_recover.c | 2 + 8 files changed, 352 insertions(+), 111 deletions(-)fs/xfs/xfs_dir2_block.c +7
-11@@ -1,5 +1,6 @@/* * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. +* Copyright (c) 2013 Red Hat, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -28,11 +29,13 @@#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_inode_item.h" +#include "xfs_buf_item.h" #include "xfs_dir2.h" #include "xfs_dir2_format.h" #include "xfs_dir2_priv.h" #include "xfs_error.h" #include "xfs_trace.h" +#include "xfs_cksum.h" /* * Local function prototypes. @@ -56,44 +59,74 @@ xfs_dir_startup(void) xfs_dir_hash_dotdot =xfs_da_hashname ((unsigned char *)".." ,2 ); } -static void -xfs_dir2_block_verify ( +static bool +xfs_dir3_block_verify (struct xfs_buf *bp) {struct xfs_mount *mp = bp->b_target->bt_mount; -struct xfs_dir2_data_hdr *hdr = bp->b_addr; -int block_ok =0 ; - - block_ok = hdr->magic ==cpu_to_be32 (XFS_DIR2_BLOCK_MAGIC ); - block_ok = block_ok &&__xfs_dir2_data_check (NULL , bp) ==0 ; - -if (!block_ok) { -XFS_CORRUPTION_ERROR (__func__,XFS_ERRLEVEL_LOW , mp, hdr); -xfs_buf_ioerror (bp,EFSCORRUPTED ); +struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; +
fs/xfs/xfs_dir2_block.c xfs_dir_startup(void) · line 78
Quoted 10 lines
fs/xfs/xfs_dir2_block.c +10
-0+if (xfs_sb_version_hascrc (&mp->m_sb)) { +if (hdr3->magic !=be32_to_cpu (XFS_DIR3_BLOCK_MAGIC )) +return false; +if (!uuid_equal (&hdr3->uuid, &mp->m_sb.sb_uuid)) +return false; +if (be64_to_cpu (hdr3->blkno) != bp->b_bn) +return false; + }else { +if (hdr3->magic !=be32_to_cpu (XFS_DIR2_BLOCK_MAGIC )) +return false;
This conditional only works because magic is in the same location in both versions of the header. It would be better to use the version two header structure explicitly here, even though it's unlikely we'd ever want to change the location of the magic.
Quoted 214 lines
fs/xfs/xfs_dir2_block.c +76
-26} +if (__xfs_dir2_data_check (NULL , bp)) +return false; +return true; }static void -xfs_dir2_block_read_verify ( +xfs_dir3_block_read_verify (struct xfs_buf *bp) { -xfs_dir2_block_verify (bp); +struct xfs_mount *mp = bp->b_target->bt_mount; + +if ((xfs_sb_version_hascrc (&mp->m_sb) && + !xfs_verify_cksum (bp->b_addr,BBTOB (bp->b_length), +XFS_DIR3_DATA_CRC_OFF )) || + !xfs_dir3_block_verify (bp)) { +XFS_CORRUPTION_ERROR (__func__,XFS_ERRLEVEL_LOW , mp, bp->b_addr); +xfs_buf_ioerror (bp,EFSCORRUPTED ); + } }static void -xfs_dir2_block_write_verify ( +xfs_dir3_block_write_verify (struct xfs_buf *bp) { -xfs_dir2_block_verify (bp); +struct xfs_mount *mp = bp->b_target->bt_mount; +struct xfs_buf_log_item *bip = bp->b_fspriv; +struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; + +if (!xfs_dir3_block_verify (bp)) { +XFS_CORRUPTION_ERROR (__func__,XFS_ERRLEVEL_LOW , mp, bp->b_addr); +xfs_buf_ioerror (bp,EFSCORRUPTED ); +return ; + } + +if (!xfs_sb_version_hascrc (&mp->m_sb)) +return ; + +if (bip) + hdr3->lsn =cpu_to_be64 (bip->bli_item.li_lsn); + +xfs_update_cksum (bp->b_addr,BBTOB (bp->b_length),XFS_DIR3_DATA_CRC_OFF ); } -const struct xfs_buf_ops xfs_dir2_block_buf_ops = { - .verify_read = xfs_dir2_block_read_verify, - .verify_write = xfs_dir2_block_write_verify, +const struct xfs_buf_ops xfs_dir3_block_buf_ops = { + .verify_read = xfs_dir3_block_read_verify, + .verify_write = xfs_dir3_block_write_verify, };static int -xfs_dir2_block_read ( +xfs_dir3_block_read (struct xfs_trans *tp,struct xfs_inode *dp,struct xfs_buf **bpp)@@ -101,7 +134,29 @@ xfs_dir2_block_read(struct xfs_mount *mp = dp->i_mount;return xfs_da_read_buf (tp, dp, mp->m_dirdatablk,-1 , bpp, -XFS_DATA_FORK , &xfs_dir2_block_buf_ops); +XFS_DATA_FORK , &xfs_dir3_block_buf_ops); +} + +static void +xfs_dir3_block_init ( +struct xfs_mount *mp, +struct xfs_buf *bp, +struct xfs_inode *dp) +{ +struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; + + bp->b_ops = &xfs_dir3_block_buf_ops; + +if (xfs_sb_version_hascrc (&mp->m_sb)) { +memset (hdr3,0 ,sizeof (*hdr3)); + hdr3->magic =cpu_to_be32 (XFS_DIR3_BLOCK_MAGIC ); + hdr3->blkno =cpu_to_be64 (bp->b_bn); + hdr3->owner =cpu_to_be64 (dp->i_ino); +uuid_copy (&hdr3->uuid, &mp->m_sb.sb_uuid); +return ; + + } + hdr3->magic =cpu_to_be32 (XFS_DIR2_BLOCK_MAGIC ); } static void@@ -121,7 +176,7 @@ xfs_dir2_block_need_space(struct xfs_dir2_data_unused *enddup =NULL ; *compact =0 ; - bf = hdr->bestfree; + bf =xfs_dir3_data_bestfree_p (hdr);/* * If there are stale entries we'll use one for the leaf. @@ -303,7 +358,7 @@ xfs_dir2_block_addname( mp = dp->i_mount;/* Read the (one and only) directory block into bp. */ - error =xfs_dir2_block_read (tp, dp, &bp); + error =xfs_dir3_block_read (tp, dp, &bp);if (error)return error;@@ -531,7 +586,7 @@ xfs_dir2_block_getdents(if (xfs_dir2_dataptr_to_db (mp, *offset) > mp->m_dirdatablk)return 0 ; - error =xfs_dir2_block_read (NULL , dp, &bp); + error =xfs_dir3_block_read (NULL , dp, &bp);if (error)return error;@@ -546,7 +601,7 @@ xfs_dir2_block_getdents(* Set up values for the loop. */ btp =xfs_dir2_block_tail_p (mp, hdr); - ptr = (char *)(hdr +1 ); + ptr = (char *)xfs_dir3_data_entry_p (hdr); endptr = (char *)xfs_dir2_block_leaf_p (btp);/* @@ -711,7 +766,7 @@ xfs_dir2_block_lookup_int( tp = args->trans; mp = dp->i_mount; - error =xfs_dir2_block_read (tp, dp, &bp); + error =xfs_dir3_block_read (tp, dp, &bp);if (error)return error;@@ -974,9 +1029,12 @@ xfs_dir2_leaf_to_block(* These will show up in the leaf bests table. */ while (dp->i_d.di_size > mp->m_dirblksize) { +int hdrsz; + + hdrsz =xfs_dir3_data_hdr_size (xfs_sb_version_hascrc (&mp->m_sb)); bestsp =xfs_dir2_leaf_bests_p (ltp);if (be16_to_cpu (bestsp[be32_to_cpu (ltp->bestcount) -1 ]) == - mp->m_dirblksize - (uint )sizeof (*hdr)) { + mp->m_dirblksize - hdrsz) {if ((error =xfs_dir2_leaf_trim_data (args, lbp, (xfs_dir2_db_t)(be32_to_cpu (ltp->bestcount) -1 ))))@@ -1014,8 +1072,8 @@ xfs_dir2_leaf_to_block(/* * Start converting it to block form. */ - dbp->b_ops = &xfs_dir2_block_buf_ops; - hdr->magic =cpu_to_be32 (XFS_DIR2_BLOCK_MAGIC ); +xfs_dir3_block_init (mp, dbp, dp); + needlog =1 ; needscan =0 ;/* @@ -1137,16 +1195,16 @@ xfs_dir2_sf_to_block(return error; }/* -* Initialize the data block. +* Initialize the data block, then convert it to block format. */ - error =xfs_dir2_data_init (args, blkno, &bp); + error =xfs_dir3_data_init (args, blkno, &bp);if (error) {kmem_free (sfp);return error; } - bp->b_ops = &xfs_dir2_block_buf_ops; +xfs_dir3_block_init (mp, bp, dp); hdr = bp->b_addr; - hdr->magic =cpu_to_be32 (XFS_DIR2_BLOCK_MAGIC ); +/* * Compute size of block "tail" area. */ @@ -1156,7 +1214,7 @@ xfs_dir2_sf_to_block(* The whole thing is initialized to free by the init routine. * Say we're using the leaf and tail area. */ - dup = (xfs_dir2_data_unused_t *)(hdr +1 ); + dup =xfs_dir3_data_unused_p (hdr); needlog = needscan =0 ;xfs_dir2_data_use_free (tp, bp, dup, mp->m_dirblksize - i, i, &needlog, &needscan);@@ -1178,8 +1236,7 @@ xfs_dir2_sf_to_block(/* * Create entry for . */ - dep = (xfs_dir2_data_entry_t *) - ((char *)hdr +XFS_DIR2_DATA_DOT_OFFSET ); + dep =xfs_dir3_data_dot_entry_p (hdr); dep->inumber =cpu_to_be64 (dp->i_ino); dep->namelen =1 ; dep->name[0 ] ='.' ;@@ -1192,8 +1249,7 @@ xfs_dir2_sf_to_block(/* * Create entry for .. */ - dep = (xfs_dir2_data_entry_t *) - ((char *)hdr +XFS_DIR2_DATA_DOTDOT_OFFSET ); + dep =xfs_dir3_data_dotdot_entry_p (hdr); dep->inumber =cpu_to_be64 (xfs_dir2_sf_get_parent_ino (sfp)); dep->namelen =2 ; dep->name[0 ] = dep->name[1 ] ='.' ;
fs/xfs/xfs_dir2_block.c xfs_dir2_sf_to_block( · line 1262
Quoted 5 lines
fs/xfs/xfs_dir2_block.c +1
-1@@ -1203,7 +1259,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_DIR2_DATA_FIRST_OFFSET ; + offset =xfs_dir3_data_first_offset (hdr);
Ah... the old macros are removed in a subsequent patch. Good.
Quoted 539 lines
fs/xfs/xfs_dir2_block.c +0
-0/* * Loop over existing entries, stuff them in. */ fs/xfs/xfs_dir2_data.c +99
-61@@ -1,5 +1,6 @@/* * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. +* Copyright (c) 2013 Red Hat, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -65,10 +66,11 @@ __xfs_dir2_data_check( mp = bp->b_target->bt_mount; hdr = bp->b_addr; - bf = hdr->bestfree; - p = (char *)(hdr +1 ); + bf =xfs_dir3_data_bestfree_p (hdr); + p = (char *)xfs_dir3_data_entry_p (hdr);switch (hdr->magic) { +case cpu_to_be32 (XFS_DIR3_BLOCK_MAGIC ):case cpu_to_be32 (XFS_DIR2_BLOCK_MAGIC ): btp =xfs_dir2_block_tail_p (mp, hdr); lep =xfs_dir2_block_leaf_p (btp);@@ -148,7 +150,8 @@ __xfs_dir2_data_check( (char *)dep - (char *)hdr); count++; lastfree =0 ; -if (hdr->magic ==cpu_to_be32 (XFS_DIR2_BLOCK_MAGIC )) { +if (hdr->magic ==cpu_to_be32 (XFS_DIR2_BLOCK_MAGIC ) || + hdr->magic ==cpu_to_be32 (XFS_DIR3_BLOCK_MAGIC )) { addr =xfs_dir2_db_off_to_dataptr (mp, mp->m_dirdatablk, (xfs_dir2_data_aoff_t) ((char *)dep - (char *)hdr));@@ -168,7 +171,8 @@ __xfs_dir2_data_check(* Need to have seen all the entries and all the bestfree slots. */ XFS_WANT_CORRUPTED_RETURN (freeseen ==7 ); -if (hdr->magic ==cpu_to_be32 (XFS_DIR2_BLOCK_MAGIC )) { +if (hdr->magic ==cpu_to_be32 (XFS_DIR2_BLOCK_MAGIC ) || + hdr->magic ==cpu_to_be32 (XFS_DIR3_BLOCK_MAGIC )) {for (i = stale =0 ; i <be32_to_cpu (btp->count); i++) {if (lep[i].address ==cpu_to_be32 (XFS_DIR2_NULL_DATAPTR ))@@ -216,7 +220,8 @@ xfs_dir2_data_reada_verify(switch (hdr->magic) {case cpu_to_be32 (XFS_DIR2_BLOCK_MAGIC ): - bp->b_ops = &xfs_dir2_block_buf_ops; +case cpu_to_be32 (XFS_DIR3_BLOCK_MAGIC ): + bp->b_ops = &xfs_dir3_block_buf_ops; bp->b_ops->verify_read (bp);return ;case cpu_to_be32 (XFS_DIR2_DATA_MAGIC ):@@ -288,12 +293,15 @@ xfs_dir2_data_freefind( {xfs_dir2_data_free_t *dfp;/* bestfree entry */ xfs_dir2_data_aoff_t off;/* offset value needed */ +struct xfs_dir2_data_free *bf;#if defined(DEBUG ) && defined(__KERNEL__)int matched;/* matched the value */ int seenzero;/* saw a 0 bestfree entry */ #endif off = (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr); + bf =xfs_dir3_data_bestfree_p (hdr); +#if defined(DEBUG ) && defined(__KERNEL__)/* * Validate some consistency in the bestfree table. @@ -301,9 +309,10 @@ xfs_dir2_data_freefind(* one we're looking for it has to be exact. */ ASSERT (hdr->magic ==cpu_to_be32 (XFS_DIR2_DATA_MAGIC ) || - hdr->magic ==cpu_to_be32 (XFS_DIR2_BLOCK_MAGIC )); -for (dfp = &hdr->bestfree[0 ], seenzero = matched =0 ; - dfp < &hdr->bestfree[XFS_DIR2_DATA_FD_COUNT ]; + hdr->magic ==cpu_to_be32 (XFS_DIR2_BLOCK_MAGIC ) || + hdr->magic ==cpu_to_be32 (XFS_DIR3_BLOCK_MAGIC )); +for (dfp = &bf[0 ], seenzero = matched =0 ; + dfp < &bf[XFS_DIR2_DATA_FD_COUNT ]; dfp++) {if (!dfp->offset) {ASSERT (!dfp->length);@@ -319,7 +328,7 @@ xfs_dir2_data_freefind( else ASSERT(be16_to_cpu(dfp->offset) + be16_to_cpu(dfp->length) <= off);ASSERT (matched ||be16_to_cpu (dfp->length) >=be16_to_cpu (dup->length)); -if (dfp > &hdr->bestfree[0 ]) +if (dfp > &bf[0 ]) ASSERT(be16_to_cpu(dfp[-1].length) >= be16_to_cpu(dfp[0].length)); }#endif @@ -328,14 +337,12 @@ xfs_dir2_data_freefind(* it can't be there since they're sorted. */ if (be16_to_cpu (dup->length) < -be16_to_cpu (hdr->bestfree[XFS_DIR2_DATA_FD_COUNT -1 ].length)) +be16_to_cpu (bf[XFS_DIR2_DATA_FD_COUNT -1 ].length))return NULL ;/* * Look at the three bestfree entries for our guy. */ -for (dfp = &hdr->bestfree[0 ]; - dfp < &hdr->bestfree[XFS_DIR2_DATA_FD_COUNT ]; - dfp++) { +for (dfp = &bf[0 ]; dfp < &bf[XFS_DIR2_DATA_FD_COUNT ]; dfp++) {if (!dfp->offset)return NULL ;if (be16_to_cpu (dfp->offset) == off)@@ -359,11 +366,12 @@ xfs_dir2_data_freeinsert(xfs_dir2_data_free_t *dfp;/* bestfree table pointer */ xfs_dir2_data_free_t new;/* new bestfree entry */ -#ifdef __KERNEL__ASSERT (hdr->magic ==cpu_to_be32 (XFS_DIR2_DATA_MAGIC ) || - hdr->magic ==cpu_to_be32 (XFS_DIR2_BLOCK_MAGIC )); -#endif - dfp = hdr->bestfree; + hdr->magic ==cpu_to_be32 (XFS_DIR2_BLOCK_MAGIC ) || + hdr->magic ==cpu_to_be32 (XFS_DIR3_DATA_MAGIC ) || + hdr->magic ==cpu_to_be32 (XFS_DIR3_BLOCK_MAGIC )); + + dfp =xfs_dir3_data_bestfree_p (hdr); new.length = dup->length; new.offset =cpu_to_be16 ((char *)dup - (char *)hdr);@@ -400,32 +408,36 @@ xfs_dir2_data_freeremove( xfs_dir2_data_free_t *dfp, /* bestfree entry pointer */ int *loghead) /* out: log data header */ { -#ifdef __KERNEL__ +struct xfs_dir2_data_free *bf; +ASSERT (hdr->magic ==cpu_to_be32 (XFS_DIR2_DATA_MAGIC ) || - hdr->magic ==cpu_to_be32 (XFS_DIR2_BLOCK_MAGIC )); -#endif + hdr->magic ==cpu_to_be32 (XFS_DIR2_BLOCK_MAGIC ) || + hdr->magic ==cpu_to_be32 (XFS_DIR3_DATA_MAGIC ) || + hdr->magic ==cpu_to_be32 (XFS_DIR3_BLOCK_MAGIC )); +/* * It's the first entry, slide the next 2 up. */ -if (dfp == &hdr->bestfree[0 ]) { - hdr->bestfree[0 ] = hdr->bestfree[1 ]; - hdr->bestfree[1 ] = hdr->bestfree[2 ]; + bf =xfs_dir3_data_bestfree_p (hdr); +if (dfp == &bf[0 ]) { + bf[0 ] = bf[1 ]; + bf[1 ] = bf[2 ]; }/* * It's the second entry, slide the 3rd entry up. */ -else if (dfp == &hdr->bestfree[1 ]) - hdr->bestfree[1 ] = hdr->bestfree[2 ]; +else if (dfp == &bf[1 ]) + bf[1 ] = bf[2 ];/* * Must be the last entry. */ else -ASSERT (dfp == &hdr->bestfree[2 ]); +ASSERT (dfp == &bf[2 ]);/* * Clear the 3rd entry, must be zero now. */ - hdr->bestfree[2 ].length =0 ; - hdr->bestfree[2 ].offset =0 ; + bf[2 ].length =0 ; + bf[2 ].offset =0 ; *loghead =1 ; }@@ -441,23 +453,26 @@ xfs_dir2_data_freescan(xfs_dir2_block_tail_t *btp;/* block tail */ xfs_dir2_data_entry_t *dep;/* active data entry */ xfs_dir2_data_unused_t *dup;/* unused data entry */ +struct xfs_dir2_data_free *bf;char *endp;/* end of block's data */ char *p;/* current entry pointer */ -#ifdef __KERNEL__ASSERT (hdr->magic ==cpu_to_be32 (XFS_DIR2_DATA_MAGIC ) || - hdr->magic ==cpu_to_be32 (XFS_DIR2_BLOCK_MAGIC )); -#endif + hdr->magic ==cpu_to_be32 (XFS_DIR2_BLOCK_MAGIC ) || + hdr->magic ==cpu_to_be32 (XFS_DIR3_BLOCK_MAGIC )); +/* * Start by clearing the table. */ -memset (hdr->bestfree,0 ,sizeof (hdr->bestfree)); + bf =xfs_dir3_data_bestfree_p (hdr); +memset (bf,0 ,sizeof (*bf) *XFS_DIR2_DATA_FD_COUNT ); *loghead =1 ;/* * Set up pointers. */ - p = (char *)(hdr +1 ); -if (hdr->magic ==cpu_to_be32 (XFS_DIR2_BLOCK_MAGIC )) { + p = (char *)xfs_dir3_data_entry_p (hdr); +if (hdr->magic ==cpu_to_be32 (XFS_DIR2_BLOCK_MAGIC ) || + hdr->magic ==cpu_to_be32 (XFS_DIR3_BLOCK_MAGIC )) { btp =xfs_dir2_block_tail_p (mp, hdr); endp = (char *)xfs_dir2_block_leaf_p (btp); }else @@ -493,7 +508,7 @@ xfs_dir2_data_freescan(* Give back the buffer for the created block. */ int /* error */ -xfs_dir2_data_init ( +xfs_dir3_data_init (xfs_da_args_t *args,/* directory operation args */ xfs_dir2_db_t blkno,/* logical dir block number */ struct xfs_buf **bpp)/* output block buffer */ @@ -502,6 +517,7 @@ xfs_dir2_data_init(xfs_dir2_data_hdr_t *hdr;/* data block header */ xfs_inode_t *dp;/* incore directory inode */ xfs_dir2_data_unused_t *dup;/* unused entry pointer */ +struct xfs_dir2_data_free *bf;int error;/* error return value */ int i;/* bestfree index */ xfs_mount_t *mp;/* filesystem mount point */ @@ -524,21 +540,34 @@ xfs_dir2_data_init(* Initialize the header. */ hdr = bp->b_addr; - hdr->magic =cpu_to_be32 (XFS_DIR2_DATA_MAGIC ); - hdr->bestfree[0 ].offset =cpu_to_be16 (sizeof (*hdr)); + +if (xfs_sb_version_hascrc (&mp->m_sb)) { +struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; + +memset (hdr3,0 ,sizeof (*hdr3)); + hdr3->magic =cpu_to_be32 (XFS_DIR3_DATA_MAGIC ); + hdr3->blkno =cpu_to_be64 (bp->b_bn); + hdr3->owner =cpu_to_be64 (dp->i_ino); +uuid_copy (&hdr3->uuid, &mp->m_sb.sb_uuid); + + }else + hdr->magic =cpu_to_be32 (XFS_DIR2_DATA_MAGIC ); + + bf =xfs_dir3_data_bestfree_p (hdr); + bf[0 ].offset =cpu_to_be16 (xfs_dir3_data_entry_offset (hdr));for (i =1 ; i <XFS_DIR2_DATA_FD_COUNT ; i++) { - hdr->bestfree[i].length =0 ; - hdr->bestfree[i].offset =0 ; + bf[i].length =0 ; + bf[i].offset =0 ; }/* * Set up an unused entry for the block's body. */ - dup = (xfs_dir2_data_unused_t *)(hdr +1 ); + dup =xfs_dir3_data_unused_p (hdr); dup->freetag =cpu_to_be16 (XFS_DIR2_DATA_FREE_TAG ); - t = mp->m_dirblksize - (uint )sizeof (*hdr); - hdr->bestfree[0 ].length =cpu_to_be16 (t); + t = mp->m_dirblksize - (uint )xfs_dir3_data_entry_offset (hdr); + bf[0 ].length =cpu_to_be16 (t); dup->length =cpu_to_be16 (t); *xfs_dir2_data_unused_tag_p (dup) =cpu_to_be16 ((char *)dup - (char *)hdr);/* @@ -562,7 +591,8 @@ xfs_dir2_data_log_entry(xfs_dir2_data_hdr_t *hdr = bp->b_addr;ASSERT (hdr->magic ==cpu_to_be32 (XFS_DIR2_DATA_MAGIC ) || - hdr->magic ==cpu_to_be32 (XFS_DIR2_BLOCK_MAGIC )); + hdr->magic ==cpu_to_be32 (XFS_DIR2_BLOCK_MAGIC ) || + hdr->magic ==cpu_to_be32 (XFS_DIR3_BLOCK_MAGIC )); xfs_trans_log_buf(tp, bp, (uint)((char *)dep - (char *)hdr), (uint)((char *)(xfs_dir2_data_entry_tag_p(dep) + 1) -@@ -580,9 +610,10 @@ xfs_dir2_data_log_header(xfs_dir2_data_hdr_t *hdr = bp->b_addr;ASSERT (hdr->magic ==cpu_to_be32 (XFS_DIR2_DATA_MAGIC ) || - hdr->magic ==cpu_to_be32 (XFS_DIR2_BLOCK_MAGIC )); + hdr->magic ==cpu_to_be32 (XFS_DIR2_BLOCK_MAGIC ) || + hdr->magic ==cpu_to_be32 (XFS_DIR3_BLOCK_MAGIC )); -xfs_trans_log_buf (tp, bp,0 ,sizeof (*hdr) -1 ); +xfs_trans_log_buf (tp, bp,0 ,xfs_dir3_data_entry_offset (hdr) -1 ); }/* @@ -597,7 +628,8 @@ xfs_dir2_data_log_unused(xfs_dir2_data_hdr_t *hdr = bp->b_addr;ASSERT (hdr->magic ==cpu_to_be32 (XFS_DIR2_DATA_MAGIC ) || - hdr->magic ==cpu_to_be32 (XFS_DIR2_BLOCK_MAGIC )); + hdr->magic ==cpu_to_be32 (XFS_DIR2_BLOCK_MAGIC ) || + hdr->magic ==cpu_to_be32 (XFS_DIR3_BLOCK_MAGIC ));/* * Log the first part of the unused entry. @@ -635,6 +667,7 @@ xfs_dir2_data_make_free(xfs_dir2_data_unused_t *newdup;/* new unused entry */ xfs_dir2_data_unused_t *postdup;/* unused entry after us */ xfs_dir2_data_unused_t *prevdup;/* unused entry before us */ +struct xfs_dir2_data_free *bf; mp = tp->t_mountp; hdr = bp->b_addr;@@ -647,7 +680,8 @@ xfs_dir2_data_make_free(else {xfs_dir2_block_tail_t *btp;/* block tail */ -ASSERT (hdr->magic ==cpu_to_be32 (XFS_DIR2_BLOCK_MAGIC )); +ASSERT (hdr->magic ==cpu_to_be32 (XFS_DIR2_BLOCK_MAGIC ) || + hdr->magic ==cpu_to_be32 (XFS_DIR3_BLOCK_MAGIC )); btp =xfs_dir2_block_tail_p (mp, hdr); endptr = (char *)xfs_dir2_block_leaf_p (btp); }@@ -655,7 +689,7 @@ xfs_dir2_data_make_free(* If this isn't the start of the block, then back up to * the previous entry and see if it's free. */ -if (offset >sizeof (*hdr)) { +if (offset >xfs_dir3_data_entry_offset (hdr)) {__be16 *tagp;/* tag just before us */ tagp = (__be16 *)((char *)hdr + offset) -1 ;@@ -681,6 +715,7 @@ xfs_dir2_data_make_free(* Previous and following entries are both free, * merge everything into a single free entry. */ + bf =xfs_dir3_data_bestfree_p (hdr);if (prevdup && postdup) {xfs_dir2_data_free_t *dfp2;/* another bestfree pointer */ @@ -695,7 +730,7 @@ xfs_dir2_data_make_free(* since the third bestfree is there, there might be more * entries. */ - needscan = (hdr->bestfree[2 ].length !=0 ); + needscan = (bf[2 ].length !=0 );/* * Fix up the new big freespace. */ @@ -711,10 +746,10 @@ xfs_dir2_data_make_free(* Remove entry 1 first then entry 0. */ ASSERT (dfp && dfp2); -if (dfp == &hdr->bestfree[1 ]) { - dfp = &hdr->bestfree[0 ]; +if (dfp == &bf[1 ]) { + dfp = &bf[0 ];ASSERT (dfp2 == dfp); - dfp2 = &hdr->bestfree[1 ]; + dfp2 = &bf[1 ]; }xfs_dir2_data_freeremove (hdr, dfp2, needlogp);xfs_dir2_data_freeremove (hdr, dfp, needlogp);@@ -722,7 +757,7 @@ xfs_dir2_data_make_free(* Now insert the new entry. */ dfp =xfs_dir2_data_freeinsert (hdr, prevdup, needlogp); -ASSERT (dfp == &hdr->bestfree[0 ]); +ASSERT (dfp == &bf[0 ]);ASSERT (dfp->length == prevdup->length);ASSERT (!dfp[1 ].length);ASSERT (!dfp[2 ].length);@@ -751,7 +786,7 @@ xfs_dir2_data_make_free(*/ else { needscan =be16_to_cpu (prevdup->length) > -be16_to_cpu (hdr->bestfree[2 ].length); +be16_to_cpu (bf[2 ].length); } }/* @@ -779,7 +814,7 @@ xfs_dir2_data_make_free(*/ else { needscan =be16_to_cpu (newdup->length) > -be16_to_cpu (hdr->bestfree[2 ].length); +be16_to_cpu (bf[2 ].length); } }/* @@ -818,10 +853,12 @@ xfs_dir2_data_use_free(xfs_dir2_data_unused_t *newdup;/* new unused entry */ xfs_dir2_data_unused_t *newdup2;/* another new unused entry */ int oldlen;/* old unused entry's length */ +struct xfs_dir2_data_free *bf; hdr = bp->b_addr;ASSERT (hdr->magic ==cpu_to_be32 (XFS_DIR2_DATA_MAGIC ) || - hdr->magic ==cpu_to_be32 (XFS_DIR2_BLOCK_MAGIC )); + hdr->magic ==cpu_to_be32 (XFS_DIR2_BLOCK_MAGIC ) || + hdr->magic ==cpu_to_be32 (XFS_DIR3_BLOCK_MAGIC ));ASSERT (be16_to_cpu (dup->freetag) ==XFS_DIR2_DATA_FREE_TAG );ASSERT (offset >= (char *)dup - (char *)hdr);ASSERT (offset + len <= (char *)dup +be16_to_cpu (dup->length) - (char *)hdr);@@ -831,7 +868,8 @@ xfs_dir2_data_use_free(*/ dfp =xfs_dir2_data_freefind (hdr, dup); oldlen =be16_to_cpu (dup->length); -ASSERT (dfp || oldlen <=be16_to_cpu (hdr->bestfree[2 ].length)); + bf =xfs_dir3_data_bestfree_p (hdr); +ASSERT (dfp || oldlen <=be16_to_cpu (bf[2 ].length));/* * Check for alignment with front and back of the entry. */ @@ -845,7 +883,7 @@ xfs_dir2_data_use_free(*/ if (matchfront && matchback) {if (dfp) { - needscan = (hdr->bestfree[2 ].offset !=0 ); + needscan = (bf[2 ].offset !=0 );if (!needscan)xfs_dir2_data_freeremove (hdr, dfp, needlogp); }@@ -875,7 +913,7 @@ xfs_dir2_data_use_free(* that means we don't know if there was a better * choice for the last slot, or not. Rescan. */ - needscan = dfp == &hdr->bestfree[2 ]; + needscan = dfp == &bf[2 ]; } }/* @@ -902,7 +940,7 @@ xfs_dir2_data_use_free(* that means we don't know if there was a better * choice for the last slot, or not. Rescan. */ - needscan = dfp == &hdr->bestfree[2 ]; + needscan = dfp == &bf[2 ]; } }/* @@ -930,7 +968,7 @@ xfs_dir2_data_use_free(* the 2 new will work. */ if (dfp) { - needscan = (hdr->bestfree[2 ].length !=0 ); + needscan = (bf[2 ].length !=0 );if (!needscan) {xfs_dir2_data_freeremove (hdr, dfp, needlogp);xfs_dir2_data_freeinsert (hdr, newdup, needlogp);fs/xfs/xfs_dir2_format.h +37
-5@@ -1,5 +1,6 @@/* * 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 @@ -36,6 +37,37 @@#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 */ + +/* * Byte offset in data block and shortform entry. */ typedef __uint16_t xfs_dir2_data_off_t ;@@ -117,19 +149,19 @@ static inline int xfs_dir2_sf_hdr_size(int i8count) (sizeof (xfs_dir2_ino8_t) -sizeof (xfs_dir2_ino4_t)); } -static inline xfs_dir2_data_aoff_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 +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 int +static inline int xfs_dir2_sf_entsize (struct xfs_dir2_sf_hdr *hdr,int len) { return sizeof(struct xfs_dir2_sf_entry) + /* namelen + offset */@@ -139,14 +171,14 @@ xfs_dir2_sf_entsize(struct xfs_dir2_sf_hdr *hdr, int len) sizeof(xfs_dir2_ino4_t)); } -static inline struct xfs_dir2_sf_entry * +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 struct xfs_dir2_sf_entry * +static inline struct xfs_dir2_sf_entry *xfs_dir2_sf_nextentry (struct xfs_dir2_sf_hdr *hdr,struct xfs_dir2_sf_entry *sfep) {
fs/xfs/xfs_dir2_format.h typedef struct xfs_dir2_data_free { · line 256
Quoted 5 lines
fs/xfs/xfs_dir2_format.h +1
-1@@ -221,11 +253,43 @@ typedef struct xfs_dir2_data_free {*/ typedef struct xfs_dir2_data_hdr { __be32 magic; /* XFS_DIR2_DATA_MAGIC or */ - /* XFS_DIR2_BLOCK_MAGIC */ + /* XFS_DIR2_BLOCK_MAGIC */
Looks like an accidental whitespace change?
Quoted 16 lines
fs/xfs/xfs_dir2_format.h +12
-0xfs_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 */
fs/xfs/xfs_dir2_format.h typedef struct xfs_dir2_data_free { · line 282
Quoted 10 lines
fs/xfs/xfs_dir2_format.h +10
-0+}; + +struct xfs_dir3_data_hdr { +struct xfs_dir3_blk_hdr hdr; +xfs_dir2_data_free_t best_free[XFS_DIR2_DATA_FD_COUNT ]; +}; + +#define XFS_DIR3_DATA_CRC_OFF offsetof(struct xfs_dir3_data_hdr, hdr.crc) + + static inline struct xfs_dir2_data_free *
Looks like an extra tab there.
Quoted 198 lines
fs/xfs/xfs_dir2_format.h +89
-0+xfs_dir3_data_bestfree_p(struct xfs_dir2_data_hdr *hdr) +{ +if (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 @@ -280,6 +344,85 @@ xfs_dir2_data_unused_tag_p(struct xfs_dir2_data_unused *dup) be16_to_cpu(dup->length) - sizeof(__be16)); } +static inline struct xfs_dir2_data_unused * +xfs_dir3_data_unused_p (struct xfs_dir2_data_hdr *hdr) +{ +if (hdr->magic ==cpu_to_be32 (XFS_DIR3_BLOCK_MAGIC )) { +return (struct xfs_dir2_data_unused *) + ((char *)hdr +sizeof (struct xfs_dir3_data_hdr )); + } +return (struct xfs_dir2_data_unused *) + ((char *)hdr +sizeof (struct xfs_dir2_data_hdr )); +} + +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)); +} + +/* +* Offsets of . and .. in data space (always block 0) +*/ +static inline xfs_dir2_data_aoff_t +xfs_dir3_data_dot_offset (struct xfs_dir2_data_hdr *hdr) +{ +return xfs_dir3_data_entry_offset (hdr); +} + +static inline xfs_dir2_data_aoff_t +xfs_dir3_data_dotdot_offset (struct xfs_dir2_data_hdr *hdr) +{ +return xfs_dir3_data_dot_offset (hdr) +xfs_dir2_data_entsize (1 ); +} + +static inline xfs_dir2_data_aoff_t +xfs_dir3_data_first_offset (struct xfs_dir2_data_hdr *hdr) +{ +return xfs_dir3_data_dotdot_offset (hdr) +xfs_dir2_data_entsize (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) +{ +return (struct xfs_dir2_data_entry *) + ((char *)hdr +xfs_dir3_data_dot_offset (hdr)); +} + +static inline struct xfs_dir2_data_entry * +xfs_dir3_data_dotdot_entry_p (struct xfs_dir2_data_hdr *hdr) +{ +return (struct xfs_dir2_data_entry *) + ((char *)hdr +xfs_dir3_data_dotdot_offset (hdr)); +} + +static inline struct xfs_dir2_data_entry * +xfs_dir3_data_first_entry_p (struct xfs_dir2_data_hdr *hdr) +{ +return (struct xfs_dir2_data_entry *) + ((char *)hdr +xfs_dir3_data_first_offset (hdr)); +} +/* * Leaf block structures. * fs/xfs/xfs_dir2_leaf.c +4
-2@@ -149,6 +149,7 @@ xfs_dir2_block_to_leaf(int needlog;/* need to log block header */ int needscan;/* need to rescan bestfree */ xfs_trans_t *tp;/* transaction pointer */ +struct xfs_dir2_data_free *bf;trace_xfs_dir2_block_to_leaf (args);@@ -177,6 +178,7 @@ xfs_dir2_block_to_leaf(xfs_dir2_data_check (dp, dbp); btp =xfs_dir2_block_tail_p (mp, hdr); blp =xfs_dir2_block_leaf_p (btp); + bf =xfs_dir3_data_bestfree_p (hdr);/* * Set the counts in the leaf header. */ @@ -212,7 +214,7 @@ xfs_dir2_block_to_leaf( ltp =xfs_dir2_leaf_tail_p (mp, leaf); ltp->bestcount =cpu_to_be32 (1 ); bestsp =xfs_dir2_leaf_bests_p (ltp); - bestsp[0 ] = hdr->bestfree[0 ].length; + bestsp[0 ] = bf[0 ].length;/* * Log the data header and leaf bests table. */ @@ -544,7 +546,7 @@ xfs_dir2_leaf_addname(/* * Initialize the block. */ -if ((error =xfs_dir2_data_init (args, use_block, &dbp))) { +if ((error =xfs_dir3_data_init (args, use_block, &dbp))) {xfs_trans_brelse (tp, lbp);return error; }fs/xfs/xfs_dir2_node.c +1
-1@@ -1588,7 +1588,7 @@ xfs_dir2_node_addname_int(if (unlikely ((error =xfs_dir2_grow_inode (args,XFS_DIR2_DATA_SPACE , &dbno)) || - (error =xfs_dir2_data_init (args, dbno, &dbp)))) + (error =xfs_dir3_data_init (args, dbno, &dbp))))return error;/* fs/xfs/xfs_dir2_priv.h +2
-2@@ -30,7 +30,7 @@ extern int xfs_dir_cilookup_result(struct xfs_da_args *args, const unsigned char *name, int len);/* xfs_dir2_block.c */ -extern const struct xfs_buf_ops xfs_dir2_block_buf_ops; +extern const struct xfs_buf_ops xfs_dir3_block_buf_ops;extern int xfs_dir2_block_addname (struct xfs_da_args *args); extern int xfs_dir2_block_getdents(struct xfs_inode *dp, void *dirent,@@ -61,7 +61,7 @@ xfs_dir2_data_freeinsert(struct xfs_dir2_data_hdr *hdr, struct xfs_dir2_data_unused *dup, int *loghead);extern void xfs_dir2_data_freescan (struct xfs_mount *mp,struct xfs_dir2_data_hdr *hdr,int *loghead); -extern int xfs_dir2_data_init (struct xfs_da_args *args,xfs_dir2_db_t blkno, +extern int xfs_dir3_data_init (struct xfs_da_args *args,xfs_dir2_db_t blkno,struct xfs_buf **bpp);extern void xfs_dir2_data_log_entry (struct xfs_trans *tp,struct xfs_buf *bp,struct xfs_dir2_data_entry *dep);fs/xfs/xfs_dir2_sf.c +1
-1@@ -278,7 +278,7 @@ xfs_dir2_block_to_sf(* Set up to loop over the block's entries. */ btp =xfs_dir2_block_tail_p (mp, hdr); - ptr = (char *)(hdr +1 ); + ptr = (char *)xfs_dir3_data_entry_p (hdr); endptr = (char *)xfs_dir2_block_leaf_p (btp); sfep =xfs_dir2_sf_firstentry (sfp);/* fs/xfs/xfs_log_recover.c +1
-0@@ -1876,6 +1876,7 @@ xlog_recover_do_reg_buffer(int bit;int nbits;int error; +struct xfs_da_blkinfo *info;trace_xfs_log_recover_buf_reg_buf (mp->m_log, buf_f);
fs/xfs/xfs_log_recover.c xlog_recover_do_reg_buffer( · line 1942
Quoted 7 lines
fs/xfs/xfs_log_recover.c +1
-0@@ -1935,6 +1936,7 @@ xlog_recover_do_reg_buffer(/* Shouldn't be any more regions */ ASSERT (i == item->ri_total); + info = bp->b_addr;switch (buf_f->blf_flags &XFS_BLF_TYPE_MASK ) {case XFS_BLF_BTREE_BUF :switch (be32_to_cpu (*(__be32 *)bp->b_addr)) {
Looks like info is not used in this patch. Maybe it snuck in from a subsequent patch?
Other than those nits, I didn't find any issues with this patch. Nice work.
-Ben
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 11/21] xfs: add CRC checks to block format directory blocks
Quoted 12 lines · Ben Myers
Quoted 9 lines · Dave Chinner
From: Dave Chinner <[email protected]>
Now that directory buffers are made from a single struct
xfs_buf, we can add CRC calculation and checking callbacks. While there, add all the fields to the on disk structures for future functionality such asd_typesupport, uuids, block numbers, owner inode, etc.To distinguish between the different on disk formats, change the magic numbers for the new format directory blocks.
Comments below.
....
Quoted 12 lines
Quoted 12 lines
fs/xfs/xfs_dir2_block.c +9
-3-if (!block_ok) { -XFS_CORRUPTION_ERROR (__func__,XFS_ERRLEVEL_LOW , mp, hdr); -xfs_buf_ioerror (bp,EFSCORRUPTED ); +struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; + +if (xfs_sb_version_hascrc (&mp->m_sb)) { +if (hdr3->magic !=be32_to_cpu (XFS_DIR3_BLOCK_MAGIC )) +return false; +if (!uuid_equal (&hdr3->uuid, &mp->m_sb.sb_uuid)) +return false; +if (be64_to_cpu (hdr3->blkno) != bp->b_bn) +return false;
Quoted 8 lines
fs/xfs/xfs_dir2_block.c xfs_dir_startup(void) · line 78
Quoted 3 lines
fs/xfs/xfs_dir2_block.c +3
-0+ }else { +if (hdr3->magic !=be32_to_cpu (XFS_DIR2_BLOCK_MAGIC )) +return false;This conditional only works because magic is in the same location in both versions of the header. It would be better to use the version two header structure explicitly here, even though it's unlikely we'd ever want to change the location of the magic.
We are never going to change the location of the magic number - it is a fundamental design premise of the entire CRC patch series that the magic numbers are always in the same place. Hence we can use the magic number to determine what the actual version of the structure is and switch appropriately.
Indeed, there's code all through this series that assumes we can use any version of the header to determine what the magic number is andhence the correct version of the header to decode it...
Quoted 10 lines
Quoted 10 lines
fs/xfs/xfs_dir2_block.c +1
-2@@ -1192,8 +1249,7 @@ xfs_dir2_sf_to_block(/* * Create entry for .. */ - dep = (xfs_dir2_data_entry_t *) - ((char *)hdr +XFS_DIR2_DATA_DOTDOT_OFFSET ); + dep =xfs_dir3_data_dotdot_entry_p (hdr); dep->inumber =cpu_to_be64 (xfs_dir2_sf_get_parent_ino (sfp)); dep->namelen =2 ; dep->name[0 ] = dep->name[1 ] ='.' ;
Quoted 8 lines
fs/xfs/xfs_dir2_block.c xfs_dir2_sf_to_block( · line 1262
Quoted 6 lines
fs/xfs/xfs_dir2_block.c +1
-1@@ -1203,7 +1259,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_DIR2_DATA_FIRST_OFFSET ; + offset =xfs_dir3_data_first_offset (hdr);Ah... the old macros are removed in a subsequent patch. Good.
Right - they are still used by the shortform directory code at this point.
Quoted 12 lines
fs/xfs/xfs_dir2_format.h typedef struct xfs_dir2_data_free { · line 256
Quoted 9 lines
fs/xfs/xfs_dir2_format.h +1
-1xfs_dir2_sf_nextentry(struct xfs_dir2_sf_hdr *hdr, struct xfs_dir2_sf_entry *sfep) {@@ -221,11 +253,43 @@ typedef struct xfs_dir2_data_free {*/ typedef struct xfs_dir2_data_hdr { __be32 magic; /* XFS_DIR2_DATA_MAGIC or */ - /* XFS_DIR2_BLOCK_MAGIC */ + /* XFS_DIR2_BLOCK_MAGIC */Looks like an accidental whitespace change?
Quoted 7 lines
fs/xfs/xfs_dir2_format.h typedef struct xfs_dir2_data_free { · line 282
Quoted 5 lines
fs/xfs/xfs_dir2_format.h +5
-0+}; + +#define XFS_DIR3_DATA_CRC_OFF offsetof(struct xfs_dir3_data_hdr, hdr.crc) + + static inline struct xfs_dir2_data_free *Looks like an extra tab there.
Fixed.
Quoted 13 lines
Quoted 13 lines
fs/xfs/xfs_log_recover.c +2
-0+++ b/fs/xfs/xfs_log_recover.c@@ -1876,6 +1876,7 @@ xlog_recover_do_reg_buffer(int bit;int nbits;int error; +struct xfs_da_blkinfo *info;trace_xfs_log_recover_buf_reg_buf (mp->m_log, buf_f);@@ -1935,6 +1936,7 @@ xlog_recover_do_reg_buffer(/* Shouldn't be any more regions */ ASSERT (i == item->ri_total);
Quoted 7 lines
fs/xfs/xfs_log_recover.c xlog_recover_do_reg_buffer( · line 1942
Quoted 4 lines
fs/xfs/xfs_log_recover.c +1
-0+ info = bp->b_addr;switch (buf_f->blf_flags &XFS_BLF_TYPE_MASK ) {case XFS_BLF_BTREE_BUF :switch (be32_to_cpu (*(__be32 *)bp->b_addr)) {Looks like info is not used in this patch. Maybe it snuck in from a subsequent patch?
Yeah, this was me starting to add magic number/verifier checks to recovery. I didn't end up adding them in each individual dir patch - I added a single patch at the end of the series that did it for all of them in one go. I'll remove this code from this patch.
Cheers,
Dave.
Signature · 7 lines
Dave Chinner [email protected] _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
PATCH 12/21 xfs: add CRC checking to dir2 free blocks
In reply to Dave ChinnerFrom: Dave Chinner <[email protected]>
This addition follows the same pattern as the dir2 block CRCs, but with a few differences. The main difference is that the free block header is different between the v2 and v3 formats, so an "in-core" free block header has been added and _todisk/_from_disk functions used to abstract the differences in structure format from the code. This is similar to the on-disk superblock versus the in-core superblock setup. The in-core strucutre is populated when the buffer is read from disk, all the in memory checks and modifications are done on the in-core version of the structure which is written back to the buffer before the buffer is logged.
--- fs/xfs/xfs_dir2_format.h | 55 +++++- fs/xfs/xfs_dir2_leaf.c | 15 +- fs/xfs/xfs_dir2_node.c | 476 +++++++++++++++++++++++++++++++--------------- 3 files changed, 384 insertions(+), 162 deletions(-)
fs/xfs/xfs_dir2_format.h +51 -4
@@ -66,6 +66,7 @@#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 */ /* * Byte offset in data block and shortform entry.
@@ -663,19 +664,65 @@ typedef struct xfs_dir2_free {/* unused entries are -1 */ } xfs_dir2_free_t; -static inline int xfs_dir2_free_max_bests (struct xfs_mount *mp) +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 */ +}; + +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) { -return (mp->m_dirblksize -sizeof (struct xfs_dir2_free_hdr )) / +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_dir2_free_max_bests (mp); +return XFS_DIR2_FREE_FIRSTDB (mp) + db /xfs_dir3_free_max_bests (mp); }/*
@@ -684,7 +731,7 @@ xfs_dir2_db_to_fdb(struct xfs_mount *mp, xfs_dir2_db_t db)static inline int xfs_dir2_db_to_fdindex (struct xfs_mount *mp,xfs_dir2_db_t db) { -return db %xfs_dir2_free_max_bests (mp); +return db %xfs_dir3_free_max_bests (mp); }/*
fs/xfs/xfs_dir2_leaf.c +8 -7
@@ -1881,6 +1881,7 @@ xfs_dir2_node_to_leaf(xfs_mount_t *mp;/* filesystem mount point */ int rval;/* successful free trim? */ xfs_trans_t *tp;/* transaction pointer */ +struct xfs_dir3_icfree_hdr freehdr;/* * There's more than a leaf level in the btree, so there must
@@ -1938,15 +1939,15 @@ xfs_dir2_node_to_leaf(if (error)return error; free = fbp->b_addr; -ASSERT (free->hdr.magic ==cpu_to_be32 (XFS_DIR2_FREE_MAGIC )); -ASSERT (!free->hdr.firstdb); +xfs_dir3_free_hdr_from_disk (&freehdr, free); + +ASSERT (!freehdr.firstdb);/* * Now see if the leafn and free data will fit in a leaf1. * If not, release the buffer and give up. */ -if (xfs_dir2_leaf_size (&leaf->hdr,be32_to_cpu (free->hdr.nvalid)) > - mp->m_dirblksize) { +if (xfs_dir2_leaf_size (&leaf->hdr, freehdr.nvalid) > mp->m_dirblksize) {xfs_trans_brelse (tp, fbp);return 0 ; }
@@ -1967,12 +1968,12 @@ xfs_dir2_node_to_leaf(* Set up the leaf tail from the freespace block. */ ltp =xfs_dir2_leaf_tail_p (mp, leaf); - ltp->bestcount = free->hdr.nvalid; + ltp->bestcount =cpu_to_be32 (freehdr.nvalid);/* * Set up the leaf bests table. */ -memcpy (xfs_dir2_leaf_bests_p (ltp), free->bests, -be32_to_cpu (ltp->bestcount) *sizeof (xfs_dir2_data_off_t)); +memcpy (xfs_dir2_leaf_bests_p (ltp),xfs_dir3_free_bests_p (mp, free), + freehdr.nvalid *sizeof (xfs_dir2_data_off_t));xfs_dir2_leaf_log_bests (tp, lbp,0 ,be32_to_cpu (ltp->bestcount) -1 );xfs_dir2_leaf_log_tail (tp, lbp);xfs_dir2_leaf_check (dp, lbp);
fs/xfs/xfs_dir2_node.c +325 -151
760 lines not on this page · raw message
Signature · 6 lines
1.7.10.4 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 12/21] xfs: add CRC checking to dir2 free blocks
Hey Dave,
Quoted 13 lines · Dave Chinner
From: Dave Chinner <[email protected]>
This addition follows the same pattern as the dir2 block CRCs, but with a few differences. The main difference is that the free block header is different between the v2 and v3 formats, so an "in-core" free block header has been added and _todisk/_from_disk functions used to abstract the differences in structure format from the code. This is similar to the on-disk superblock versus the in-core superblock setup. The in-core strucutre is populated when the buffer is read from disk, all the in memory checks and modifications are done on the in-core version of the structure which is written back to the buffer before the buffer is logged.
Quoted 1 line
Signed-off-by Dave Chinner <[email protected]>
Just a few nits below.
Quoted 20 lines
fs/xfs/xfs_dir2_node.c +7
-8-static void -xfs_dir2_free_verify ( +static bool +xfs_dir3_free_verify (struct xfs_buf *bp) {struct xfs_mount *mp = bp->b_target->bt_mount;struct xfs_dir2_free_hdr *hdr = bp->b_addr; -int block_ok =0 ; - block_ok = hdr->magic ==cpu_to_be32 (XFS_DIR2_FREE_MAGIC ); -if (!block_ok) { -XFS_CORRUPTION_ERROR ("xfs_dir2_free_verify magic" , -XFS_ERRLEVEL_LOW , mp, hdr); -xfs_buf_ioerror (bp,EFSCORRUPTED ); +if (xfs_sb_version_hascrc (&mp->m_sb)) { +struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; + +if (hdr3->magic !=be32_to_cpu (XFS_DIR3_FREE_MAGIC )) +return false;
fs/xfs/xfs_dir2_node.c static int xfs_dir2_leafn_remove(xfs_da_args_t *args, struct xfs_buf *bp, · line 82
Quoted 10 lines
fs/xfs/xfs_dir2_node.c +9
-0+if (!uuid_equal (&hdr3->uuid, &mp->m_sb.sb_uuid)) +return false; +if (be64_to_cpu (hdr3->blkno) != bp->b_bn) +return false; + }else { +if (hdr->magic !=be32_to_cpu (XFS_DIR2_FREE_MAGIC )) +return false; } + +/* XXX: should bounds check the xfs_dir3_icfree_hdr here */
What did you have in mind?
Quoted 8 lines
fs/xfs/xfs_dir2_node.c +8
-0+static int +xfs_dir3_free_get_buf ( +struct xfs_trans *tp, +struct xfs_inode *dp, +xfs_dir2_db_t fbno, +struct xfs_buf **bpp) +{ +struct xfs_mount *mp = dp->i_mount;
fs/xfs/xfs_dir2_node.c xfs_dir2_free_try_read( · line 227
Quoted 10 lines
fs/xfs/xfs_dir2_node.c +10
-0+struct xfs_buf *bp; +int error; +struct xfs_dir3_icfree_hdr hdr; + + error =xfs_da_get_buf (tp, dp,xfs_dir2_db_to_da (mp, fbno), +-1 , &bp,XFS_DATA_FORK ); +if (error) +return error; + + bp->b_ops = &xfs_dir3_free_buf_ops;;
Extra ;
Quoted 7 lines
fs/xfs/xfs_dir2_node.c +7
-0+ +/* +* Initialize the new block to be empty, and remember +* its first slot as our empty slot. +*/ + hdr.magic =XFS_DIR2_FREE_MAGIC ; + hdr.firstdb =0 ;
fs/xfs/xfs_dir2_node.c xfs_dir2_free_try_read( · line 244
Quoted 10 lines
fs/xfs/xfs_dir2_node.c +10
-0+ hdr.nused =0 ; + hdr.nvalid =0 ; +if (xfs_sb_version_hascrc (&mp->m_sb)) { +struct xfs_dir3_free_hdr *hdr3 = bp->b_addr; + + hdr.magic =XFS_DIR3_FREE_MAGIC ; + hdr3->hdr.blkno =cpu_to_be64 (bp->b_bn); + hdr3->hdr.owner =cpu_to_be64 (dp->i_ino); +uuid_copy (&hdr3->hdr.uuid, &mp->m_sb.sb_uuid); +
Extra line
Quoted 7 lines
fs/xfs/xfs_dir2_node.c +4
-0+ } +xfs_dir3_free_hdr_to_disk (bp->b_addr, &hdr); + *bpp = bp; +return 0 ; }/*
...
fs/xfs/xfs_dir2_node.c xfs_dir2_data_block_free( · line 1063
Quoted 6 lines
fs/xfs/xfs_dir2_node.c +2
-0@@ -909,59 +1059,68 @@ xfs_dir2_data_block_free( {struct xfs_trans *tp = args->trans;int logfree =0 ; +__be16 *bests; +struct xfs_dir3_icfree_hdr freehdr;
Seems to be an extra line in this function here, although you don't see it added in the patch.
fs/xfs/xfs_dir2_node.c xfs_dir2_data_block_free( · line 922
Quoted 11 lines
fs/xfs/xfs_dir2_node.c +0
-9-if (!hdr) { -/* One less used entry in the free table. */ -be32_add_cpu (&free->hdr.nused,-1 ); -xfs_dir2_free_log_header (tp, fbp); -/* -* If this was the last entry in the table, we can trim the -* table size back. There might be other entries at the end -* referring to non-existent data blocks, get those too. -*/
You dropped this comment. Was there something wrong with it?
Quoted 80 lines
fs/xfs/xfs_dir2_node.c +44
-29-if (findex ==be32_to_cpu (free->hdr.nvalid) -1 ) { -int i;/* free entry index */ +xfs_dir3_free_hdr_from_disk (&freehdr, free); -for (i = findex -1 ; i >=0 ; i--) { -if (free->bests[i] !=cpu_to_be16 (NULLDATAOFF )) -break ; - } - free->hdr.nvalid =cpu_to_be32 (i +1 ); - logfree =0 ; - }else { -/* Not the last entry, just punch it out. */ - free->bests[findex] =cpu_to_be16 (NULLDATAOFF ); - logfree =1 ; - } + bests =xfs_dir3_free_bests_p (tp->t_mountp, free); +if (hdr) {/* -* If there are no useful entries left in the block, -* get rid of the block if we can. +* Data block is not empty, just set the free entry to the new +* value. */ -if (!free->hdr.nused) { -int error; + bests[findex] =cpu_to_be16 (longest); +xfs_dir2_free_log_bests (tp, fbp, findex, findex); +return 0 ; + } - error =xfs_dir2_shrink_inode (args, fdb, fbp); -if (error ==0 ) { - fbp =NULL ; - logfree =0 ; - }else if (error !=ENOSPC || args->total !=0 ) -return error; -/* -* It's possible to get ENOSPC if there is no -* space reservation. In this case some one -* else will eventually get rid of this block. -*/ +/* +* One less used entry in the free table. Unused is not converted +* because we only need to know if it zero +*/ + freehdr.nused--; + +if (findex == freehdr.nvalid -1 ) { +int i;/* free entry index */ + +for (i = findex -1 ; i >=0 ; i--) { +if (bests[i] !=cpu_to_be16 (NULLDATAOFF )) +break ; } + freehdr.nvalid = i +1 ; + logfree =0 ; }else { +/* Not the last entry, just punch it out. */ + bests[findex] =cpu_to_be16 (NULLDATAOFF ); + logfree =1 ; + } + +xfs_dir3_free_hdr_to_disk (free, &freehdr); +xfs_dir2_free_log_header (tp, fbp); + +/* +* If there are no useful entries left in the block, get rid of the +* block if we can. +*/ +if (!freehdr.nused) { +int error; + + error =xfs_dir2_shrink_inode (args, fdb, fbp); +if (error ==0 ) { + fbp =NULL ; + logfree =0 ; + }else if (error !=ENOSPC || args->total !=0 ) +return error;/* -* Data block is not empty, just set the free entry to the new
fs/xfs/xfs_dir2_node.c xfs_dir2_data_block_free( · line 1123
Quoted 10 lines
fs/xfs/xfs_dir2_node.c +4
-3-* value. +* It's possible to get ENOSPC if there is no +* space reservation. In this case some one +* else will eventually get rid of this block. */ - free->bests[findex] =cpu_to_be16 (longest); - logfree =1 ; } +
Extra line.
Quoted 6 lines
fs/xfs/xfs_dir2_node.c +0
-0/* Log the free entry that changed, unless we got rid of it. */ if (logfree)xfs_dir2_free_log_bests (tp, fbp, findex, findex);@@ -1062,10 +1221,15 @@ xfs_dir2_leafn_remove(if (error)return error;
fs/xfs/xfs_dir2_node.c xfs_dir2_leafn_remove( · line 1228
Quoted 10 lines
fs/xfs/xfs_dir2_node.c +5
-4free = fbp->b_addr; -ASSERT (free->hdr.magic ==cpu_to_be32 (XFS_DIR2_FREE_MAGIC )); -ASSERT (be32_to_cpu (free->hdr.firstdb) == -xfs_dir2_free_max_bests (mp) * - (fdb -XFS_DIR2_FREE_FIRSTDB (mp))); +#ifdef DEBUG + { +struct xfs_dir3_icfree_hdr freehdr; +xfs_dir3_free_hdr_from_disk (&freehdr, free); + ASSERT(be32_to_cpu(freehdr.firstdb) ==
I think freehdr.firstdb is already in cpu endianness.
fs/xfs/xfs_dir2_node.c xfs_dir2_node_addname_int( · line 1722
Quoted 11 lines
fs/xfs/xfs_dir2_node.c +2
-1@@ -1547,20 +1714,26 @@ xfs_dir2_node_addname_int(if (!fbp)continue ; free = fbp->b_addr; -ASSERT (free->hdr.magic ==cpu_to_be32 (XFS_DIR2_FREE_MAGIC )); findex =0 ; }/* * Look at the current free entry. Is it good enough? +* +* The bests initialisation should be wher eteh bufer is read in
where the buffer
fs/xfs/xfs_dir2_node.c xfs_dir2_node_addname_int( · line 1724
Quoted 2 lines
fs/xfs/xfs_dir2_node.c +2
-0+* the above branch. But gcc is too stupid to realise that bests +* iand the freehdr are actually initialised if they are placed
and
Quoted 2 lines
fs/xfs/xfs_dir2_node.c +1
-0+* there, so we have to do it here to avoid warnings. Blech. */
...
fs/xfs/xfs_dir2_node.c xfs_dir2_node_addname_int( · line 1790
Quoted 8 lines
fs/xfs/xfs_dir2_node.c +1
-3@@ -1614,11 +1787,11 @@ xfs_dir2_node_addname_int(* If there wasn't a freespace block, the read will * return a NULL fbp. Allocate and initialize a new one. */ -if ( fbp ==NULL ) { -if ((error =xfs_dir2_grow_inode (args,XFS_DIR2_FREE_SPACE , - &fbno))) { +if (!fbp) {
Add a space before the opening paren.
Looks good.
Regards,
Ben
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 12/21] xfs: add CRC checking to dir2 free blocks
Quoted 44 lines · Ben Myers
Hey Dave,
Quoted 13 lines · Dave Chinner
From: Dave Chinner <[email protected]>
This addition follows the same pattern as the dir2 block CRCs, but with a few differences. The main difference is that the free block header is different between the v2 and v3 formats, so an "in-core" free block header has been added and _todisk/_from_disk functions used to abstract the differences in structure format from the code. This is similar to the on-disk superblock versus the in-core superblock setup. The in-core strucutre is populated when the buffer is read from disk, all the in memory checks and modifications are done on the in-core version of the structure which is written back to the buffer before the buffer is logged.
Quoted 1 line
Signed-off-by Dave Chinner <[email protected]>Just a few nits below.
Quoted 24 lines
fs/xfs/xfs_dir2_node.c +11
-8-static void -xfs_dir2_free_verify ( +static bool +xfs_dir3_free_verify (struct xfs_buf *bp) {struct xfs_mount *mp = bp->b_target->bt_mount;struct xfs_dir2_free_hdr *hdr = bp->b_addr; -int block_ok =0 ; - block_ok = hdr->magic ==cpu_to_be32 (XFS_DIR2_FREE_MAGIC ); -if (!block_ok) { -XFS_CORRUPTION_ERROR ("xfs_dir2_free_verify magic" , -XFS_ERRLEVEL_LOW , mp, hdr); -xfs_buf_ioerror (bp,EFSCORRUPTED ); +if (xfs_sb_version_hascrc (&mp->m_sb)) { +struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; + +if (hdr3->magic !=be32_to_cpu (XFS_DIR3_FREE_MAGIC )) +return false; +if (!uuid_equal (&hdr3->uuid, &mp->m_sb.sb_uuid)) +return false; +if (be64_to_cpu (hdr3->blkno) != bp->b_bn) +return false;
Quoted 8 lines
fs/xfs/xfs_dir2_node.c static int xfs_dir2_leafn_remove(xfs_da_args_t *args, struct xfs_buf *bp, · line 82
Quoted 6 lines
fs/xfs/xfs_dir2_node.c +5
-0+ }else { +if (hdr->magic !=be32_to_cpu (XFS_DIR2_FREE_MAGIC )) +return false; } + +/* XXX: should bounds check the xfs_dir3_icfree_hdr here */ What did you have in mind?
Checking that the header fields:
a) are within valid bounds; and
b) match what is in the bests array.
Quoted 5 lines
Quoted 5 lines
fs/xfs/xfs_dir2_node.c +0
-4-if (!hdr) { -/* One less used entry in the free table. */ -be32_add_cpu (&free->hdr.nused,-1 ); -xfs_dir2_free_log_header (tp, fbp);
Quoted 7 lines
fs/xfs/xfs_dir2_node.c xfs_dir2_data_block_free( · line 922
Quoted 5 lines
fs/xfs/xfs_dir2_node.c +0
-5-/* -* If this was the last entry in the table, we can trim the -* table size back. There might be other entries at the end -* referring to non-existent data blocks, get those too. -*/ You dropped this comment. Was there something wrong with it?
No, just an oversight when rearranging the code.
Quoted 10 lines
Quoted 10 lines
fs/xfs/xfs_dir2_node.c +0
-3/* Log the free entry that changed, unless we got rid of it. */ if (logfree)xfs_dir2_free_log_bests (tp, fbp, findex, findex);@@ -1062,10 +1221,15 @@ xfs_dir2_leafn_remove(if (error)return error; free = fbp->b_addr; -ASSERT (free->hdr.magic ==cpu_to_be32 (XFS_DIR2_FREE_MAGIC )); -ASSERT (be32_to_cpu (free->hdr.firstdb) == - xfs_dir2_free_max_bests(mp) *
Quoted 8 lines
fs/xfs/xfs_dir2_node.c xfs_dir2_leafn_remove( · line 1228
Quoted 6 lines
fs/xfs/xfs_dir2_node.c +5
-1- (fdb - XFS_DIR2_FREE_FIRSTDB(mp))); +#ifdef DEBUG + { +struct xfs_dir3_icfree_hdr freehdr; +xfs_dir3_free_hdr_from_disk (&freehdr, free); + ASSERT(be32_to_cpu(freehdr.firstdb) ==I think freehdr.firstdb is already in cpu endianness.
Right. Well spotted. I've already posted a fix for it - sparse endian checking picked this up. My current series folds those fixes back into the original patches....
Cheers,
Dave.
Signature · 7 lines
Dave Chinner [email protected] _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
PATCH 13/21 xfs: add CRC checking to dir2 data blocks
In reply to Dave ChinnerFrom: Dave Chinner <[email protected]>
This addition follows the same pattern as the dir2 block CRCs.
--- fs/xfs/xfs_dir2_block.c | 22 +++++----- fs/xfs/xfs_dir2_data.c | 100 ++++++++++++++++++++++++++++++++-------------- fs/xfs/xfs_dir2_format.h | 21 +++++----- fs/xfs/xfs_dir2_leaf.c | 71 ++++++++++++++++++-------------- fs/xfs/xfs_dir2_node.c | 39 ++++++++++-------- fs/xfs/xfs_dir2_priv.h | 12 +++--- fs/xfs/xfs_file.c | 2 +- 7 files changed, 162 insertions(+), 105 deletions(-)
fs/xfs/xfs_dir2_block.c +12 -10
@@ -77,7 +77,7 @@ xfs_dir3_block_verify(if (hdr3->magic !=be32_to_cpu (XFS_DIR2_BLOCK_MAGIC ))return false; } -if (__xfs_dir2_data_check (NULL , bp)) +if (__xfs_dir3_data_check (NULL , bp))return false;return true; }
@@ -553,7 +553,7 @@ xfs_dir2_block_addname(xfs_dir2_data_log_header (tp, bp);xfs_dir2_block_log_tail (tp, bp);xfs_dir2_data_log_entry (tp, bp, dep); -xfs_dir2_data_check (dp, bp); +xfs_dir3_data_check (dp, bp);return 0 ; }
@@ -596,7 +596,7 @@ xfs_dir2_block_getdents(*/ wantoff =xfs_dir2_dataptr_to_off (mp, *offset); hdr = bp->b_addr; -xfs_dir2_data_check (dp, bp); +xfs_dir3_data_check (dp, bp);/* * Set up values for the loop. */
@@ -720,7 +720,7 @@ xfs_dir2_block_lookup( dp = args->dp; mp = dp->i_mount; hdr = bp->b_addr; -xfs_dir2_data_check (dp, bp); +xfs_dir3_data_check (dp, bp); btp =xfs_dir2_block_tail_p (mp, hdr); blp =xfs_dir2_block_leaf_p (btp);/*
@@ -771,7 +771,7 @@ xfs_dir2_block_lookup_int(return error; hdr = bp->b_addr; -xfs_dir2_data_check (dp, bp); +xfs_dir3_data_check (dp, bp); btp =xfs_dir2_block_tail_p (mp, hdr); blp =xfs_dir2_block_leaf_p (btp);/*
@@ -908,7 +908,7 @@ xfs_dir2_block_removename(xfs_dir2_data_freescan (mp, hdr, &needlog);if (needlog)xfs_dir2_data_log_header (tp, bp); -xfs_dir2_data_check (dp, bp); +xfs_dir3_data_check (dp, bp);/* * See if the size as a shortform is good enough. */
@@ -965,7 +965,7 @@ xfs_dir2_block_replace(*/ dep->inumber =cpu_to_be64 (args->inumber);xfs_dir2_data_log_entry (args->trans, bp, dep); -xfs_dir2_data_check (dp, bp); +xfs_dir3_data_check (dp, bp);return 0 ; }
@@ -1046,12 +1046,14 @@ xfs_dir2_leaf_to_block(* Read the data block if we don't already have it, give up if it fails. */ if (!dbp) { - error =xfs_dir2_data_read (tp, dp, mp->m_dirdatablk,-1 , &dbp); + error =xfs_dir3_data_read (tp, dp, mp->m_dirdatablk,-1 , &dbp);if (error)return error; } hdr = dbp->b_addr; -ASSERT (hdr->magic ==cpu_to_be32 (XFS_DIR2_DATA_MAGIC )); +ASSERT (hdr->magic ==cpu_to_be32 (XFS_DIR2_DATA_MAGIC ) || + hdr->magic ==cpu_to_be32 (XFS_DIR3_DATA_MAGIC )); +/* * Size of the "leaf" area in the block. */
@@ -1329,6 +1331,6 @@ xfs_dir2_sf_to_block(ASSERT (needscan ==0 );xfs_dir2_block_log_leaf (tp, bp,0 ,be32_to_cpu (btp->count) -1 );xfs_dir2_block_log_tail (tp, bp); -xfs_dir2_data_check (dp, bp); +xfs_dir3_data_check (dp, bp);return 0 ; }
fs/xfs/xfs_dir2_data.c +70 -30
230 lines not on this page · raw message
fs/xfs/xfs_dir2_format.h +9 -12
@@ -283,7 +283,8 @@ struct xfs_dir3_data_hdr {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_BLOCK_MAGIC )) { +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; }
@@ -345,17 +346,6 @@ xfs_dir2_data_unused_tag_p(struct xfs_dir2_data_unused *dup) be16_to_cpu(dup->length) - sizeof(__be16)); } -static inline struct xfs_dir2_data_unused * -xfs_dir3_data_unused_p (struct xfs_dir2_data_hdr *hdr) -{ -if (hdr->magic ==cpu_to_be32 (XFS_DIR3_BLOCK_MAGIC )) { -return (struct xfs_dir2_data_unused *) - ((char *)hdr +sizeof (struct xfs_dir3_data_hdr )); - } -return (struct xfs_dir2_data_unused *) - ((char *)hdr +sizeof (struct xfs_dir2_data_hdr )); -} -static inline size_t xfs_dir3_data_hdr_size (bool dir3) {
@@ -379,6 +369,13 @@ xfs_dir3_data_entry_p(struct xfs_dir2_data_hdr *hdr) ((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) */
fs/xfs/xfs_dir2_leaf.c +41 -30
223 lines not on this page · raw message
fs/xfs/xfs_dir2_node.c +23 -16
@@ -754,13 +754,13 @@ xfs_dir2_leafn_lookup_for_entry(ASSERT (state->extravalid); curbp = state->extrablk.bp; }else { - error =xfs_dir2_data_read (tp, dp, + error =xfs_dir3_data_read (tp, dp,xfs_dir2_db_to_da (mp, newdb),-1 , &curbp);if (error)return error; } -xfs_dir2_data_check (dp, curbp); +xfs_dir3_data_check (dp, curbp); curdb = newdb; }/*
@@ -788,7 +788,7 @@ xfs_dir2_leafn_lookup_for_entry( state->extrablk.index = (int )((char *)dep - (char *)curbp->b_addr); state->extrablk.magic =XFS_DIR2_DATA_MAGIC ; - curbp->b_ops = &xfs_dir2_data_buf_ops; + curbp->b_ops = &xfs_dir3_data_buf_ops;if (cmp ==XFS_CMP_EXACT )return XFS_ERROR (EEXIST ); }
@@ -803,7 +803,7 @@ xfs_dir2_leafn_lookup_for_entry( state->extrablk.index =-1 ; state->extrablk.blkno = curdb; state->extrablk.magic =XFS_DIR2_DATA_MAGIC ; - curbp->b_ops = &xfs_dir2_data_buf_ops; + curbp->b_ops = &xfs_dir3_data_buf_ops; }else {/* If the curbp is not the CI match block, drop it */ if (state->extrablk.bp != curbp)
@@ -1153,6 +1153,7 @@ xfs_dir2_leafn_remove(int needlog;/* need to log data header */ int needscan;/* need to rescan data frees */ xfs_trans_t *tp;/* transaction pointer */ +struct xfs_dir2_data_free *bf;/* bestfree table */ trace_xfs_dir2_leafn_remove (args, index);
@@ -1187,7 +1188,8 @@ xfs_dir2_leafn_remove( dbp = dblk->bp; hdr = dbp->b_addr; dep = (xfs_dir2_data_entry_t *)((char *)hdr + off); - longest =be16_to_cpu (hdr->bestfree[0 ].length); + bf =xfs_dir3_data_bestfree_p (hdr); + longest =be16_to_cpu (bf[0 ].length); needlog = needscan =0 ;xfs_dir2_data_make_free (tp, dbp, off,xfs_dir2_data_entsize (dep->namelen), &needlog, &needscan);
@@ -1199,12 +1201,12 @@ xfs_dir2_leafn_remove(xfs_dir2_data_freescan (mp, hdr, &needlog);if (needlog)xfs_dir2_data_log_header (tp, dbp); -xfs_dir2_data_check (dp, dbp); +xfs_dir3_data_check (dp, dbp);/* * If the longest data block freespace changes, need to update * the corresponding freeblock entry. */ -if (longest <be16_to_cpu (hdr->bestfree[0 ].length)) { +if (longest <be16_to_cpu (bf[0 ].length)) {int error;/* error return value */ struct xfs_buf *fbp;/* freeblock buffer */ xfs_dir2_db_t fdb;/* freeblock block number */
@@ -1234,12 +1236,13 @@ xfs_dir2_leafn_remove(* Calculate which entry we need to fix. */ findex =xfs_dir2_db_to_fdindex (mp, db); - longest =be16_to_cpu (hdr->bestfree[0 ].length); + longest =be16_to_cpu (bf[0 ].length);/* * If the data block is now empty we can get rid of it * (usually). */ -if (longest == mp->m_dirblksize - (uint )sizeof (*hdr)) { +if (longest == mp->m_dirblksize - +xfs_dir3_data_entry_offset (hdr)) {/* * Try to punch out the data block. */
@@ -1613,6 +1616,7 @@ xfs_dir2_node_addname_int(xfs_trans_t *tp;/* transaction pointer */ __be16 *bests;struct xfs_dir3_icfree_hdr freehdr; +struct xfs_dir2_data_free *bf; dp = args->dp; mp = dp->i_mount;
@@ -1870,7 +1874,8 @@ xfs_dir2_node_addname_int(* change again. */ hdr = dbp->b_addr; - bests[findex] = hdr->bestfree[0 ].length; + bf =xfs_dir3_data_bestfree_p (hdr); + bests[findex] = bf[0 ].length; logfree =1 ; }/*
@@ -1886,19 +1891,20 @@ xfs_dir2_node_addname_int(/* * Read the data block in. */ - error =xfs_dir2_data_read (tp, dp,xfs_dir2_db_to_da (mp, dbno), + error =xfs_dir3_data_read (tp, dp,xfs_dir2_db_to_da (mp, dbno),-1 , &dbp);if (error)return error; hdr = dbp->b_addr; + bf =xfs_dir3_data_bestfree_p (hdr); logfree =0 ; } -ASSERT (be16_to_cpu (hdr->bestfree[0 ].length) >= length); +ASSERT (be16_to_cpu (bf[0 ].length) >= length);/* * Point to the existing unused space. */ dup = (xfs_dir2_data_unused_t *) - ((char *)hdr +be16_to_cpu (hdr->bestfree[0 ].offset)); + ((char *)hdr +be16_to_cpu (bf[0 ].offset)); needscan = needlog =0 ;/* * Mark the first part of the unused space, inuse for us.
@@ -1930,8 +1936,8 @@ xfs_dir2_node_addname_int(* If the freespace entry is now wrong, update it. */ bests =xfs_dir3_free_bests_p (mp, free);/* gcc is so stupid */ -if (be16_to_cpu (bests[findex]) !=be16_to_cpu (hdr->bestfree[0 ].length)) { - bests[findex] = hdr->bestfree[0 ].length; +if (be16_to_cpu (bests[findex]) !=be16_to_cpu (bf[0 ].length)) { + bests[findex] = bf[0 ].length; logfree =1 ; }/*
@@ -2121,7 +2127,8 @@ xfs_dir2_node_replace(* Point to the data entry. */ hdr = state->extrablk.bp->b_addr; -ASSERT (hdr->magic ==cpu_to_be32 (XFS_DIR2_DATA_MAGIC )); +ASSERT (hdr->magic ==cpu_to_be32 (XFS_DIR2_DATA_MAGIC ) || + hdr->magic ==cpu_to_be32 (XFS_DIR3_DATA_MAGIC )); dep = (xfs_dir2_data_entry_t *) ((char *)hdr +xfs_dir2_dataptr_to_off (state->mp,be32_to_cpu (lep->address)));
fs/xfs/xfs_dir2_priv.h +6 -6
@@ -43,17 +43,17 @@ extern int xfs_dir2_leaf_to_block(struct xfs_da_args *args,/* xfs_dir2_data.c */ #ifdef DEBUG -#define xfs_dir2_data_check (dp,bp) __xfs_dir2_data_check(dp, bp); +#define xfs_dir3_data_check (dp,bp) __xfs_dir3_data_check(dp, bp);#else -#define xfs_dir2_data_check (dp,bp) +#define xfs_dir3_data_check (dp,bp)#endif -extern const struct xfs_buf_ops xfs_dir2_data_buf_ops; +extern const struct xfs_buf_ops xfs_dir3_data_buf_ops; -extern int __xfs_dir2_data_check (struct xfs_inode *dp,struct xfs_buf *bp); -extern int xfs_dir2_data_read (struct xfs_trans *tp,struct xfs_inode *dp, +extern int __xfs_dir3_data_check (struct xfs_inode *dp,struct xfs_buf *bp); +extern int xfs_dir3_data_read (struct xfs_trans *tp,struct xfs_inode *dp,xfs_dablk_t bno,xfs_daddr_t mapped_bno,struct xfs_buf **bpp); -extern int xfs_dir2_data_readahead (struct xfs_trans *tp,struct xfs_inode *dp, +extern int xfs_dir3_data_readahead (struct xfs_trans *tp,struct xfs_inode *dp,xfs_dablk_t bno,xfs_daddr_t mapped_bno); extern struct xfs_dir2_data_free *
fs/xfs/xfs_file.c +1 -1
@@ -915,7 +915,7 @@ xfs_dir_open(*/ mode =xfs_ilock_map_shared (ip);if (ip->i_d.di_nextents >0 ) -xfs_dir2_data_readahead (NULL , ip,0 ,-1 ); +xfs_dir3_data_readahead (NULL , ip,0 ,-1 );xfs_iunlock (ip, mode);return 0 ; }
Signature · 6 lines
1.7.10.4 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 13/21] xfs: add CRC checking to dir2 data blocks
Dave,
Quoted 5 lines · Dave Chinner
From: Dave Chinner <[email protected]>
This addition follows the same pattern as the dir2 block CRCs.
Signed-off-by Dave Chinner <[email protected]>
Just a few nits.
fs/xfs/xfs_dir2_block.c xfs_dir2_block_removename( · line 911
Quoted 6 lines
fs/xfs/xfs_dir2_block.c +1
-1@@ -908,7 +908,7 @@ xfs_dir2_block_removename(xfs_dir2_data_freescan (mp, hdr, &needlog);if (needlog)xfs_dir2_data_log_header (tp, bp); -xfs_dir2_data_check (dp, bp); +xfs_dir3_data_check (dp, bp);
In this debug code, maybe it is better check the blocks after making the changes to them but before logging them? Not sure.
Quoted 10 lines
fs/xfs/xfs_dir2_data.c +1
-1@@ -212,7 +221,7 @@ xfs_dir2_data_verify(* format buffer or a data format buffer on readahead. */ static void -xfs_dir2_data_reada_verify ( +xfs_dir3_data_reada_verify (struct xfs_buf *bp) {struct xfs_mount *mp = bp->b_target->bt_mount;
fs/xfs/xfs_dir2_data.c xfs_dir2_data_reada_verify( · line 238
Quoted 6 lines
fs/xfs/xfs_dir2_data.c +2
-1@@ -225,7 +234,8 @@ xfs_dir2_data_reada_verify( bp->b_ops->verify_read (bp);return ;case cpu_to_be32 (XFS_DIR2_DATA_MAGIC ): -xfs_dir2_data_verify (bp); +case cpu_to_be32 (XFS_DIR3_DATA_MAGIC ): +xfs_dir3_data_verify (bp);
I think it might be a good idea to add a print in the situation where we have an error in readahead. It needn't be a forced shutdown.
fs/xfs/xfs_dir2_format.h struct xfs_dir3_data_hdr { · line 284
Quoted 7 lines
fs/xfs/xfs_dir2_format.h +0
-0@@ -283,7 +283,8 @@ struct xfs_dir3_data_hdr {static inline struct xfs_dir2_data_free *xfs_dir3_data_bestfree_p (struct xfs_dir2_data_hdr *hdr)
Get rid of the tab.
fs/xfs/xfs_dir2_format.h xfs_dir2_block_to_leaf( · line 212
Quoted 12 lines
fs/xfs/xfs_dir2_format.h +6
-2@@ -204,8 +204,12 @@ xfs_dir2_block_to_leaf(/* * Fix up the block header, make it a data block. */ - dbp->b_ops = &xfs_dir2_data_buf_ops; - hdr->magic =cpu_to_be32 (XFS_DIR2_DATA_MAGIC ); + dbp->b_ops = &xfs_dir3_data_buf_ops; +if (hdr->magic ==cpu_to_be32 (XFS_DIR2_BLOCK_MAGIC )) + hdr->magic =cpu_to_be32 (XFS_DIR2_DATA_MAGIC ); +else + hdr->magic =cpu_to_be32 (XFS_DIR3_DATA_MAGIC ); +
else {
ASSERT(hdr->magic == XFS_DIR3_BLOCK_MAGIC));
hdr->magic = cpu_to_be32(XFS_DIR3_DATA_MAGIC);
}Might be nice...
Else, looks good. I'll switch over to reviewing your new rev.
Regards,
Ben
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
PATCH 14/21 xfs: add CRC checking to dir2 leaf blocks
In reply to Dave ChinnerFrom: Dave Chinner <[email protected]>
This addition follows the same pattern as the dir2 block CRCs. Seeing as both LEAF1 and LEAFN types need to changed at the same time, this is a pretty large amount of change. leaf block headers neeed to be abstracted away from the on-disk structures (struct xfs_dir3_icleaf_hdr), as do the base leaf entry locations.
This header abstract allows the in-core header and leaf entry location to be passed around instead of the leaf block itself. This saves a lot of converting individual variables from on-disk format to host format where they are used, so there's a good chance that the compiler will be able to produce much more optimal code as it's not having to byteswap variables all over the place.
--- fs/xfs/xfs_da_btree.c | 45 ++- fs/xfs/xfs_da_btree.h | 23 ++ fs/xfs/xfs_dir2_block.c | 19 +- fs/xfs/xfs_dir2_format.h | 60 +++- fs/xfs/xfs_dir2_leaf.c | 785 +++++++++++++++++++++++++++++----------------- fs/xfs/xfs_dir2_node.c | 458 +++++++++++++++------------ fs/xfs/xfs_dir2_priv.h | 32 +- 7 files changed, 908 insertions(+), 514 deletions(-)
fs/xfs/xfs_da_btree.c +35 -10
@@ -139,7 +139,8 @@ xfs_da_node_read_verify( bp->b_ops->verify_read (bp);return ;case XFS_DIR2_LEAFN_MAGIC : - bp->b_ops = &xfs_dir2_leafn_buf_ops; +case XFS_DIR3_LEAFN_MAGIC : + bp->b_ops = &xfs_dir3_leafn_buf_ops; bp->b_ops->verify_read (bp);return ;default :
@@ -396,11 +397,18 @@ xfs_da_root_split(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, size = (int )((char *)&oldroot->btree[be16_to_cpu (oldroot->hdr.count)] - (char *)oldroot); }else { -ASSERT (oldroot->hdr.info.magic ==cpu_to_be16 (XFS_DIR2_LEAFN_MAGIC )); +struct xfs_dir3_icleaf_hdr leafhdr; +struct xfs_dir2_leaf_entry *ents; + leaf = (xfs_dir2_leaf_t *)oldroot; - size = (int )((char *)&leaf->ents[be16_to_cpu (leaf->hdr.count)] - - (char *)leaf); +xfs_dir3_leaf_hdr_from_disk (&leafhdr, leaf); + ents =xfs_dir3_leaf_ents_p (leaf); + +ASSERT (leafhdr.magic ==XFS_DIR2_LEAFN_MAGIC || + leafhdr.magic ==XFS_DIR3_LEAFN_MAGIC ); + size = (int )((char *)&ents[leafhdr.count] - (char *)leaf); } +/* XXX: can't just copy CRC headers from one block to another */ memcpy (node, oldroot, size);xfs_trans_log_buf (tp, bp,0 , size -1 );
@@ -424,7 +432,8 @@ xfs_da_root_split(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, node->hdr.count =cpu_to_be16 (2 );#ifdef DEBUG -if (oldroot->hdr.info.magic ==cpu_to_be16 (XFS_DIR2_LEAFN_MAGIC )) { +if (oldroot->hdr.info.magic ==cpu_to_be16 (XFS_DIR2_LEAFN_MAGIC ) || + oldroot->hdr.info.magic ==cpu_to_be16 (XFS_DIR3_LEAFN_MAGIC )) {ASSERT (blk1->blkno >= mp->m_dirleafblk && blk1->blkno < mp->m_dirfreeblk); ASSERT(blk2->blkno >= mp->m_dirleafblk &&
@@ -782,6 +791,7 @@ xfs_da_blkinfo_onlychild_validate(struct xfs_da_blkinfo *blkinfo, __u16 level)if (level ==1 ) {ASSERT (magic ==cpu_to_be16 (XFS_DIR2_LEAFN_MAGIC ) || + magic ==cpu_to_be16 (XFS_DIR3_LEAFN_MAGIC ) || magic ==cpu_to_be16 (XFS_ATTR_LEAF_MAGIC )); }else ASSERT (magic ==cpu_to_be16 (XFS_DA_NODE_MAGIC ));
@@ -1565,6 +1575,7 @@ xfs_da_path_shift(xfs_da_state_t *state, xfs_da_state_path_t *path, info = blk->bp->b_addr;ASSERT (info->magic ==cpu_to_be16 (XFS_DA_NODE_MAGIC ) || info->magic ==cpu_to_be16 (XFS_DIR2_LEAFN_MAGIC ) || + info->magic ==cpu_to_be16 (XFS_DIR3_LEAFN_MAGIC ) || info->magic ==cpu_to_be16 (XFS_ATTR_LEAF_MAGIC )); blk->magic =be16_to_cpu (info->magic);if (blk->magic ==XFS_DA_NODE_MAGIC ) {
@@ -1584,12 +1595,13 @@ xfs_da_path_shift(xfs_da_state_t *state, xfs_da_state_path_t *path, NULL);break ;case XFS_DIR2_LEAFN_MAGIC : +case XFS_DIR3_LEAFN_MAGIC : + blk->magic =XFS_DIR2_LEAFN_MAGIC ; blk->hashval =xfs_dir2_leafn_lasthash (blk->bp,NULL );break ;default : -ASSERT (blk->magic ==XFS_ATTR_LEAF_MAGIC || - blk->magic ==XFS_DIR2_LEAFN_MAGIC ); +ASSERT (0 );break ; } }
@@ -1833,10 +1845,16 @@ xfs_da_swap_lastblock(/* * Get values from the moved block. */ -if (dead_info->magic ==cpu_to_be16 (XFS_DIR2_LEAFN_MAGIC )) { +if (dead_info->magic ==cpu_to_be16 (XFS_DIR2_LEAFN_MAGIC ) || + dead_info->magic ==cpu_to_be16 (XFS_DIR3_LEAFN_MAGIC )) { +struct xfs_dir3_icleaf_hdr leafhdr; +struct xfs_dir2_leaf_entry *ents; + dead_leaf2 = (xfs_dir2_leaf_t *)dead_info; +xfs_dir3_leaf_hdr_from_disk (&leafhdr, dead_leaf2); + ents =xfs_dir3_leaf_ents_p (dead_leaf2); dead_level =0 ; - dead_hash =be32_to_cpu (dead_leaf2->ents[be16_to_cpu (dead_leaf2->hdr.count) -1 ].hashval); + dead_hash =be32_to_cpu (ents[leafhdr.count -1 ].hashval); }else {ASSERT (dead_info->magic ==cpu_to_be16 (XFS_DA_NODE_MAGIC )); dead_node = (xfs_da_intnode_t *)dead_info;
@@ -2281,10 +2299,17 @@ xfs_da_read_buf( XFS_TEST_ERROR((magic != XFS_DA_NODE_MAGIC) && (magic != XFS_ATTR_LEAF_MAGIC) && (magic != XFS_DIR2_LEAF1_MAGIC) && + (magic != XFS_DIR3_LEAF1_MAGIC) && (magic != XFS_DIR2_LEAFN_MAGIC) && + (magic != XFS_DIR3_LEAFN_MAGIC) && (magic1 != XFS_DIR2_BLOCK_MAGIC) && + (magic1 != XFS_DIR3_BLOCK_MAGIC) && (magic1 != XFS_DIR2_DATA_MAGIC) && - (free->hdr.magic != cpu_to_be32(XFS_DIR2_FREE_MAGIC)), + (magic1 != XFS_DIR3_DATA_MAGIC) && + (free->hdr.magic != + cpu_to_be32(XFS_DIR2_FREE_MAGIC)) && + (free->hdr.magic != + cpu_to_be32(XFS_DIR3_FREE_MAGIC)), mp, XFS_ERRTAG_DA_READ_BUF, XFS_RANDOM_DA_READ_BUF))) {trace_xfs_da_btree_corrupt (bp, _RET_IP_);
fs/xfs/xfs_da_btree.h +23 -0
@@ -47,6 +47,29 @@ typedef struct xfs_da_blkinfo { } 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. +*/ +#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. *
fs/xfs/xfs_dir2_block.c +12 -7
@@ -1013,6 +1013,8 @@ xfs_dir2_leaf_to_block(__be16 *tagp;/* end of entry (tag) */ int to;/* block/leaf to index */ xfs_trans_t *tp;/* transaction pointer */ +struct xfs_dir2_leaf_entry *ents; +struct xfs_dir3_icleaf_hdr leafhdr;trace_xfs_dir2_leaf_to_block (args);
@@ -1020,8 +1022,12 @@ xfs_dir2_leaf_to_block( tp = args->trans; mp = dp->i_mount; leaf = lbp->b_addr; -ASSERT (leaf->hdr.info.magic ==cpu_to_be16 (XFS_DIR2_LEAF1_MAGIC )); +xfs_dir3_leaf_hdr_from_disk (&leafhdr, leaf); + ents =xfs_dir3_leaf_ents_p (leaf); ltp =xfs_dir2_leaf_tail_p (mp, leaf); + +ASSERT (leafhdr.magic ==XFS_DIR2_LEAF1_MAGIC || + leafhdr.magic ==XFS_DIR3_LEAF1_MAGIC );/* * If there are data blocks other than the first one, take this * opportunity to remove trailing empty data blocks that may have
@@ -1058,7 +1064,7 @@ xfs_dir2_leaf_to_block(* Size of the "leaf" area in the block. */ size = (uint )sizeof (xfs_dir2_block_tail_t) + - (uint )sizeof (*lep) * (be16_to_cpu (leaf->hdr.count) -be16_to_cpu (leaf->hdr.stale)); + (uint )sizeof (*lep) * (leafhdr.count - leafhdr.stale);/* * Look at the last data entry. */
@@ -1087,18 +1093,17 @@ xfs_dir2_leaf_to_block(* Initialize the block tail. */ btp =xfs_dir2_block_tail_p (mp, hdr); - btp->count =cpu_to_be32 (be16_to_cpu (leaf->hdr.count) -be16_to_cpu (leaf->hdr.stale)); + btp->count =cpu_to_be32 (leafhdr.count - leafhdr.stale); btp->stale =0 ;xfs_dir2_block_log_tail (tp, dbp);/* * Initialize the block leaf area. We compact out stale entries. */ lep =xfs_dir2_block_leaf_p (btp); -for (from = to =0 ; from <be16_to_cpu (leaf->hdr.count); from++) { -if (leaf->ents[from].address == -cpu_to_be32 (XFS_DIR2_NULL_DATAPTR )) +for (from = to =0 ; from < leafhdr.count; from++) { +if (ents[from].address ==cpu_to_be32 (XFS_DIR2_NULL_DATAPTR ))continue ; - lep[to++] = leaf->ents[from]; + lep[to++] = ents[from]; }ASSERT (to ==be32_to_cpu (btp->count));xfs_dir2_block_log_leaf (tp, dbp,0 ,be32_to_cpu (btp->count) -1 );
fs/xfs/xfs_dir2_format.h +53 -7
88 lines not on this page · raw message
fs/xfs/xfs_dir2_leaf.c +500 -285
1,359 lines not on this page · raw message
fs/xfs/xfs_dir2_node.c +265 -193
779 lines not on this page · raw message
fs/xfs/xfs_dir2_priv.h +20 -12
@@ -77,24 +77,25 @@ extern void xfs_dir2_data_use_free(struct xfs_trans *tp, struct xfs_buf *bp, xfs_dir2_data_aoff_t len, int *needlogp, int *needscanp);/* xfs_dir2_leaf.c */ -extern const struct xfs_buf_ops xfs_dir2_leafn_buf_ops; +extern const struct xfs_buf_ops xfs_dir3_leafn_buf_ops; -extern int xfs_dir2_leafn_read (struct xfs_trans *tp,struct xfs_inode *dp, +extern int xfs_dir3_leafn_read (struct xfs_trans *tp,struct xfs_inode *dp,xfs_dablk_t fbno,xfs_daddr_t mappedbno,struct xfs_buf **bpp);extern int xfs_dir2_block_to_leaf (struct xfs_da_args *args,struct xfs_buf *dbp);extern int xfs_dir2_leaf_addname (struct xfs_da_args *args); -extern void xfs_dir2_leaf_compact (struct xfs_da_args *args, -struct xfs_buf *bp); -extern void xfs_dir2_leaf_compact_x1 (struct xfs_buf *bp,int *indexp, +extern void xfs_dir3_leaf_compact (struct xfs_da_args *args, +struct xfs_dir3_icleaf_hdr *leafhdr,struct xfs_buf *bp); +extern void xfs_dir3_leaf_compact_x1 (struct xfs_dir3_icleaf_hdr *leafhdr, +struct xfs_dir2_leaf_entry *ents,int *indexp,int *lowstalep,int *highstalep,int *lowlogp,int *highlogp);extern int xfs_dir2_leaf_getdents (struct xfs_inode *dp,void *dirent,size_t bufsize,xfs_off_t *offset,filldir_t filldir); -extern int xfs_dir2_leaf_init (struct xfs_da_args *args,xfs_dir2_db_t bno, -struct xfs_buf **bpp,int magic); -extern void xfs_dir2_leaf_log_ents (struct xfs_trans *tp,struct xfs_buf *bp, +extern int xfs_dir3_leaf_get_buf (struct xfs_da_args *args,xfs_dir2_db_t bno, +struct xfs_buf **bpp,__uint16_t magic); +extern void xfs_dir3_leaf_log_ents (struct xfs_trans *tp,struct xfs_buf *bp,int first,int last); -extern void xfs_dir2_leaf_log_header (struct xfs_trans *tp, +extern void xfs_dir3_leaf_log_header (struct xfs_trans *tp,struct xfs_buf *bp);extern int xfs_dir2_leaf_lookup (struct xfs_da_args *args);extern int xfs_dir2_leaf_removename (struct xfs_da_args *args);
@@ -104,11 +105,18 @@ extern int xfs_dir2_leaf_search_hash(struct xfs_da_args *args,extern int xfs_dir2_leaf_trim_data (struct xfs_da_args *args,struct xfs_buf *lbp,xfs_dir2_db_t db);extern struct xfs_dir2_leaf_entry * -xfs_dir2_leaf_find_entry (struct xfs_dir2_leaf *leaf,int index,int compact, -int lowstale,int highstale, -int *lfloglow,int *lfloghigh); +xfs_dir3_leaf_find_entry (struct xfs_dir3_icleaf_hdr *leafhdr, +struct xfs_dir2_leaf_entry *ents,int index,int compact, +int lowstale,int highstale,int *lfloglow,int *lfloghigh);extern int xfs_dir2_node_to_leaf (struct xfs_da_state *state); +extern void xfs_dir3_leaf_hdr_from_disk (struct xfs_dir3_icleaf_hdr *to, +struct xfs_dir2_leaf *from); +extern void xfs_dir3_leaf_hdr_to_disk (struct xfs_dir2_leaf *to, +struct xfs_dir3_icleaf_hdr *from); +extern bool xfs_dir3_leaf_check_int (struct xfs_mount *mp, +struct xfs_dir3_icleaf_hdr *hdr,struct xfs_dir2_leaf *leaf); +/* xfs_dir2_node.c */ extern int xfs_dir2_leaf_to_node (struct xfs_da_args *args,struct xfs_buf *lbp);
Signature · 6 lines
1.7.10.4 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
PATCH 15/21 xfs: shortform directory offsets change for dir3 format
In reply to Dave ChinnerFrom: Dave Chinner <[email protected]>
Because the header size for the CRC enabled directory blocks is larger, the offset of the first entry into a directory block is different to the dir2 format. The shortform directory stores the dirent's offset so that it doesn't change when moving from shortform to block form and back again, and hence it needs to take into account the different header sizes to maintain the correct offsets.
--- fs/xfs/xfs_dir2_format.h | 25 ++++++++++++++----------- fs/xfs/xfs_dir2_sf.c | 10 +++++----- 2 files changed, 19 insertions(+), 16 deletions(-)
fs/xfs/xfs_dir2_format.h +14 -11
@@ -228,16 +228,6 @@ xfs_dir2_sf_nextentry(struct xfs_dir2_sf_hdr *hdr,xfs_dir2_byte_to_db (mp,XFS_DIR2_DATA_OFFSET )/* -* Offsets of . and .. in data space (always block 0) - */ -#define XFS_DIR2_DATA_DOT_OFFSET \ - ((xfs_dir2_data_aoff_t)sizeof(struct xfs_dir2_data_hdr)) -#define XFS_DIR2_DATA_DOTDOT_OFFSET \ - (XFS_DIR2_DATA_DOT_OFFSET + xfs_dir2_data_entsize(1)) -#define XFS_DIR2_DATA_FIRST_OFFSET \ - (XFS_DIR2_DATA_DOTDOT_OFFSET + xfs_dir2_data_entsize(2)) - -/* * Describe a free area in the data block. * * The freespace will be formatted as a xfs_dir2_data_unused_t.
@@ -378,7 +368,20 @@ 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. +*/ +#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_dir2_data_entsize(1)) +#define XFS_DIR3_DATA_FIRST_OFFSET (mp) \ + (XFS_DIR3_DATA_DOTDOT_OFFSET(mp) + xfs_dir2_data_entsize(2)) +static inline xfs_dir2_data_aoff_t xfs_dir3_data_dot_offset (struct xfs_dir2_data_hdr *hdr) {
fs/xfs/xfs_dir2_sf.c +5 -5
@@ -535,7 +535,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_DIR2_DATA_FIRST_OFFSET, + for (offset = XFS_DIR3_DATA_FIRST_OFFSET(dp->i_mount), oldsfep = xfs_dir2_sf_firstentry(oldsfp), add_datasize = xfs_dir2_data_entsize(args->namelen), eof = (char *)oldsfep == &buf[old_isize];
@@ -617,7 +617,7 @@ xfs_dir2_sf_addname_pick( sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; size =xfs_dir2_data_entsize (args->namelen); - offset =XFS_DIR2_DATA_FIRST_OFFSET ; + offset =XFS_DIR3_DATA_FIRST_OFFSET (mp); sfep =xfs_dir2_sf_firstentry (sfp); holefit =0 ;/*
@@ -688,7 +688,7 @@ xfs_dir2_sf_check( dp = args->dp; sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; - offset =XFS_DIR2_DATA_FIRST_OFFSET ; + offset =XFS_DIR3_DATA_FIRST_OFFSET (dp->i_mount); ino =xfs_dir2_sf_get_parent_ino (sfp); i8count = ino >XFS_DIR2_MAX_SHORT_INUM ;
@@ -812,9 +812,9 @@ xfs_dir2_sf_getdents(* mp->m_dirdatablk. */ dot_offset =xfs_dir2_db_off_to_dataptr (mp, mp->m_dirdatablk, -XFS_DIR2_DATA_DOT_OFFSET ); +XFS_DIR3_DATA_DOT_OFFSET (mp)); dotdot_offset =xfs_dir2_db_off_to_dataptr (mp, mp->m_dirdatablk, -XFS_DIR2_DATA_DOTDOT_OFFSET ); +XFS_DIR3_DATA_DOTDOT_OFFSET (mp));/* * Put . entry unless we're starting past it.
Signature · 6 lines
1.7.10.4 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
PATCH 16/21 xfs: add CRCs to dir2/da node blocks
In reply to Dave ChinnerFrom: Dave Chinner <[email protected]>
--- fs/xfs/xfs_attr.c | 33 +- fs/xfs/xfs_attr_leaf.c | 29 +- fs/xfs/xfs_bmap.c | 1 + fs/xfs/xfs_da_btree.c | 1395 +++++++++++++++++++++++++++++------------------- fs/xfs/xfs_da_btree.h | 106 +++- fs/xfs/xfs_dir2_node.c | 26 +- fs/xfs/xfs_trace.c | 2 +- 7 files changed, 972 insertions(+), 620 deletions(-)
fs/xfs/xfs_attr.c +16 -17
@@ -15,7 +15,6 @@* along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "xfs.h" #include "xfs_fs.h" #include "xfs_types.h"
@@ -25,6 +24,7 @@#include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" +#include "xfs_error.h" #include "xfs_da_btree.h" #include "xfs_bmap_btree.h" #include "xfs_attr_sf.h"
@@ -35,7 +35,6 @@#include "xfs_bmap.h" #include "xfs_attr.h" #include "xfs_attr_leaf.h" -#include "xfs_error.h" #include "xfs_quota.h" #include "xfs_trans_space.h" #include "xfs_vnodeops.h"
@@ -1236,7 +1235,7 @@ restart:* Search to see if name already exists, and get back a pointer * to where it should go. */ - error =xfs_da_node_lookup_int (state, &retval); + error =xfs_da3_node_lookup_int (state, &retval);if (error) goto out; blk = &state->path.blk[ state->path.active-1 ];
@@ -1307,7 +1306,7 @@ restart:* in the index2/blkno2/rmtblkno2/rmtblkcnt2 fields. */ xfs_bmap_init (args->flist, args->firstblock); - error =xfs_da_split (state); + error =xfs_da3_split (state);if (!error) { error =xfs_bmap_finish (&args->trans, args->flist, &committed);
@@ -1329,7 +1328,7 @@ restart:/* * Addition succeeded, update Btree hashvals. */ -xfs_da_fixhashpath (state, &state->path); +xfs_da3_fixhashpath (state, &state->path); }/*
@@ -1400,7 +1399,7 @@ restart: state->blocksize = state->mp->m_sb.sb_blocksize; state->node_ents = state->mp->m_attr_node_ents; state->inleaf =0 ; - error =xfs_da_node_lookup_int (state, &retval); + error =xfs_da3_node_lookup_int (state, &retval);if (error) goto out;
@@ -1410,14 +1409,14 @@ restart: blk = &state->path.blk[ state->path.active-1 ];ASSERT (blk->magic ==XFS_ATTR_LEAF_MAGIC ); error =xfs_attr_leaf_remove (blk->bp, args); -xfs_da_fixhashpath (state, &state->path); +xfs_da3_fixhashpath (state, &state->path);/* * Check to see if the tree needs to be collapsed. */ if (retval && (state->path.active >1 )) {xfs_bmap_init (args->flist, args->firstblock); - error =xfs_da_join (state); + error =xfs_da3_join (state);if (!error) { error = xfs_bmap_finish(&args->trans, args->flist,
@@ -1495,7 +1494,7 @@ xfs_attr_node_removename(xfs_da_args_t *args)/* * Search to see if name exists, and get back a pointer to it. */ - error =xfs_da_node_lookup_int (state, &retval); + error =xfs_da3_node_lookup_int (state, &retval);if (error || (retval !=EEXIST )) {if (error ==0 ) error = retval;
@@ -1546,14 +1545,14 @@ xfs_attr_node_removename(xfs_da_args_t *args) blk = &state->path.blk[ state->path.active-1 ];ASSERT (blk->magic ==XFS_ATTR_LEAF_MAGIC ); retval =xfs_attr_leaf_remove (blk->bp, args); -xfs_da_fixhashpath (state, &state->path); +xfs_da3_fixhashpath (state, &state->path);/* * Check to see if the tree needs to be collapsed. */ if (retval && (state->path.active >1 )) {xfs_bmap_init (args->flist, args->firstblock); - error =xfs_da_join (state); + error =xfs_da3_join (state);if (!error) { error =xfs_bmap_finish (&args->trans, args->flist, &committed);
@@ -1699,7 +1698,7 @@ xfs_attr_refillstate(xfs_da_state_t *state)ASSERT ((path->active >=0 ) && (path->active <XFS_DA_NODE_MAXDEPTH ));for (blk = path->blk, level =0 ; level < path->active; blk++, level++) {if (blk->disk_blkno) { - error =xfs_da_node_read (state->args->trans, + error =xfs_da3_node_read (state->args->trans, state->args->dp, blk->blkno, blk->disk_blkno, &blk->bp,XFS_ATTR_FORK );
@@ -1718,7 +1717,7 @@ xfs_attr_refillstate(xfs_da_state_t *state)ASSERT ((path->active >=0 ) && (path->active <XFS_DA_NODE_MAXDEPTH ));for (blk = path->blk, level =0 ; level < path->active; blk++, level++) {if (blk->disk_blkno) { - error =xfs_da_node_read (state->args->trans, + error =xfs_da3_node_read (state->args->trans, state->args->dp, blk->blkno, blk->disk_blkno, &blk->bp,XFS_ATTR_FORK );
@@ -1758,7 +1757,7 @@ xfs_attr_node_get(xfs_da_args_t *args)/* * Search to see if name exists, and get back a pointer to it. */ - error =xfs_da_node_lookup_int (state, &retval); + error =xfs_da3_node_lookup_int (state, &retval);if (error) { retval = error; }else if (retval ==EEXIST ) {
@@ -1810,7 +1809,7 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)*/ bp =NULL ;if (cursor->blkno >0 ) { - error =xfs_da_node_read (NULL , context->dp, cursor->blkno,-1 , + error =xfs_da3_node_read (NULL , context->dp, cursor->blkno,-1 , &bp,XFS_ATTR_FORK );if ((error !=0 ) && (error !=EFSCORRUPTED ))return (error);
@@ -1852,7 +1851,7 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)if (bp ==NULL ) { cursor->blkno =0 ;for (;;) { - error =xfs_da_node_read (NULL , context->dp, + error =xfs_da3_node_read (NULL , context->dp, cursor->blkno,-1 , &bp,XFS_ATTR_FORK );if (error)
@@ -1870,7 +1869,7 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)xfs_trans_brelse (NULL , bp);return (XFS_ERROR (EFSCORRUPTED )); } - btree = node->btree; + btree =xfs_da3_node_tree_p (node);for (i =0 ; i <be16_to_cpu (node->hdr.count); btree++, i++) { if (cursor->hashval
fs/xfs/xfs_attr_leaf.c +16 -13
@@ -910,6 +910,7 @@ xfs_attr_leaf_to_node(xfs_da_args_t *args)struct xfs_buf *bp1, *bp2;xfs_dablk_t blkno;int error; +struct xfs_da_node_entry *btree;trace_xfs_attr_leaf_to_node (args);
@@ -935,16 +936,16 @@ xfs_attr_leaf_to_node(xfs_da_args_t *args)/* * Set up the new root node. */ - error =xfs_da_node_create (args,0 ,1 , &bp1,XFS_ATTR_FORK ); + error =xfs_da3_node_create (args,0 ,1 , &bp1,XFS_ATTR_FORK );if (error) goto out; node = bp1->b_addr; leaf = bp2->b_addr;ASSERT (leaf->hdr.info.magic ==cpu_to_be16 (XFS_ATTR_LEAF_MAGIC ));/* both on-disk, don't endian-flip twice */ - node->btree[0 ].hashval = - leaf->entries[be16_to_cpu (leaf->hdr.count)-1 ].hashval; - node->btree[0 ].before =cpu_to_be32 (blkno); + btree =xfs_da3_node_tree_p (node); + btree[0 ].hashval = leaf->entries[be16_to_cpu (leaf->hdr.count)-1 ].hashval; + btree[0 ].before =cpu_to_be32 (blkno); node->hdr.count =cpu_to_be16 (1 );xfs_trans_log_buf (args->trans, bp1,0 ,XFS_LBSIZE (dp->i_mount) -1 ); error =0 ;
@@ -1032,7 +1033,7 @@ xfs_attr_leaf_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk,* NOTE: rebalance() currently depends on the 2nd block being empty. */ xfs_attr_leaf_rebalance (state, oldblk, newblk); - error =xfs_da_blk_link (state, oldblk, newblk); + error =xfs_da3_blk_link (state, oldblk, newblk);if (error)return (error);
@@ -1660,7 +1661,7 @@ xfs_attr_leaf_toosmall(xfs_da_state_t *state, int *action)*/ forward = (info->forw !=0 );memcpy (&state->altpath, &state->path,sizeof (state->path)); - error =xfs_da_path_shift (state, &state->altpath, forward, + error =xfs_da3_path_shift (state, &state->altpath, forward,0 , &retval);if (error)return (error);
@@ -1717,10 +1718,10 @@ xfs_attr_leaf_toosmall(xfs_da_state_t *state, int *action)*/ memcpy (&state->altpath, &state->path,sizeof (state->path));if (blkno < blk->blkno) { - error =xfs_da_path_shift (state, &state->altpath, forward, + error =xfs_da3_path_shift (state, &state->altpath, forward,0 , &retval); }else { - error =xfs_da_path_shift (state, &state->path, forward, + error =xfs_da3_path_shift (state, &state->path, forward,0 , &retval); }if (error)
@@ -2783,7 +2784,7 @@ xfs_attr_root_inactive(xfs_trans_t **trans, xfs_inode_t *dp)* the extents in reverse order the extent containing * block 0 must still be there. */ - error =xfs_da_node_read (*trans, dp,0 ,-1 , &bp,XFS_ATTR_FORK ); + error =xfs_da3_node_read (*trans, dp,0 ,-1 , &bp,XFS_ATTR_FORK );if (error)return (error); blkno =XFS_BUF_ADDR (bp);
@@ -2836,6 +2837,7 @@ xfs_attr_node_inactive(xfs_daddr_t parent_blkno, child_blkno;int error, count, i;struct xfs_buf *child_bp; +struct xfs_da_node_entry *btree;/* * Since this code is recursive (gasp!) we must protect ourselves.
@@ -2853,7 +2855,8 @@ xfs_attr_node_inactive(xfs_trans_brelse (*trans, bp);return (0 ); } - child_fsb =be32_to_cpu (node->btree[0 ].before); + btree =xfs_da3_node_tree_p (node); + child_fsb =be32_to_cpu (btree[0 ].before);xfs_trans_brelse (*trans, bp);/* no locks for later trans */ /*
@@ -2868,7 +2871,7 @@ xfs_attr_node_inactive(* traversal of the tree so we may deal with many blocks * before we come back to this one. */ - error =xfs_da_node_read (*trans, dp, child_fsb,-2 , &child_bp, + error =xfs_da3_node_read (*trans, dp, child_fsb,-2 , &child_bp,XFS_ATTR_FORK );if (error)return (error);
@@ -2909,11 +2912,11 @@ xfs_attr_node_inactive(* child block number. */ if ((i+1 ) < count) { - error =xfs_da_node_read (*trans, dp,0 , parent_blkno, + error =xfs_da3_node_read (*trans, dp,0 , parent_blkno, &bp,XFS_ATTR_FORK );if (error)return (error); - child_fsb =be32_to_cpu (node->btree[i+1 ].before); + child_fsb =be32_to_cpu (btree[i+1 ].before);xfs_trans_brelse (*trans, bp); }/*
fs/xfs/xfs_bmap.c +1 -0
@@ -25,6 +25,7 @@#include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_dir2.h" +#include "xfs_mount.h" #include "xfs_da_btree.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h"
fs/xfs/xfs_da_btree.c +842 -553
2,166 lines not on this page · raw message
fs/xfs/xfs_da_btree.h +83 -23
151 lines not on this page · raw message
fs/xfs/xfs_dir2_node.c +13 -13
@@ -1366,7 +1366,7 @@ xfs_dir2_leafn_split(* block into the leaves. */ xfs_dir2_leafn_rebalance (state, oldblk, newblk); - error =xfs_da_blk_link (state, oldblk, newblk); + error =xfs_da3_blk_link (state, oldblk, newblk);if (error) {return error; }
@@ -1448,7 +1448,7 @@ xfs_dir2_leafn_toosmall(*/ forward = (leafhdr.forw !=0 );memcpy (&state->altpath, &state->path,sizeof (state->path)); - error =xfs_da_path_shift (state, &state->altpath, forward,0 , + error =xfs_da3_path_shift (state, &state->altpath, forward,0 , &rval);if (error)return error;
@@ -1510,10 +1510,10 @@ xfs_dir2_leafn_toosmall(*/ memcpy (&state->altpath, &state->path,sizeof (state->path));if (blkno < blk->blkno) - error =xfs_da_path_shift (state, &state->altpath, forward,0 , + error =xfs_da3_path_shift (state, &state->altpath, forward,0 , &rval);else - error =xfs_da_path_shift (state, &state->path, forward,0 , + error =xfs_da3_path_shift (state, &state->path, forward,0 , &rval);if (error) {return error;
@@ -1609,7 +1609,7 @@ xfs_dir2_node_addname(* Look up the name. We're not supposed to find it, but * this gives us the insertion point. */ - error =xfs_da_node_lookup_int (state, &rval); + error =xfs_da3_node_lookup_int (state, &rval);if (error) rval = error;if (rval !=ENOENT ) {
@@ -1635,7 +1635,7 @@ xfs_dir2_node_addname(* It worked, fix the hash values up the btree. */ if (!(args->op_flags &XFS_DA_OP_JUSTCHECK )) -xfs_da_fixhashpath (state, &state->path); +xfs_da3_fixhashpath (state, &state->path); }else {/* * It didn't work, we need to split the leaf block.
@@ -1647,7 +1647,7 @@ xfs_dir2_node_addname(/* * Split the leaf block and insert the new entry. */ - rval =xfs_da_split (state); + rval =xfs_da3_split (state); } done:xfs_da_state_free (state);
@@ -2025,7 +2025,7 @@ xfs_dir2_node_addname_int(/* * Lookup an entry in a node-format directory. -* All the real work happens in xfs_da_node_lookup_int. +* All the real work happens in xfs_da3_node_lookup_int. * The only real output is the inode number of the entry. */ int /* error */
@@ -2050,7 +2050,7 @@ xfs_dir2_node_lookup(/* * Fill in the path to the entry in the cursor. */ - error =xfs_da_node_lookup_int (state, &rval); + error =xfs_da3_node_lookup_int (state, &rval);if (error) rval = error;else if (rval ==ENOENT && args->cmpresult ==XFS_CMP_CASE ) {
@@ -2105,7 +2105,7 @@ xfs_dir2_node_removename(/* * Look up the entry we're deleting, set up the cursor. */ - error =xfs_da_node_lookup_int (state, &rval); + error =xfs_da3_node_lookup_int (state, &rval);if (error) rval = error;/*
@@ -2129,12 +2129,12 @@ xfs_dir2_node_removename(/* * Fix the hash values up the btree. */ -xfs_da_fixhashpath (state, &state->path); +xfs_da3_fixhashpath (state, &state->path);/* * If we need to join leaf blocks, do it. */ if (rval && state->path.active >1 ) - error =xfs_da_join (state); + error =xfs_da3_join (state);/* * If no errors so far, try conversion to leaf format. */
@@ -2176,7 +2176,7 @@ xfs_dir2_node_replace(/* * Lookup the entry to change in the btree. */ - error =xfs_da_node_lookup_int (state, &rval); + error =xfs_da3_node_lookup_int (state, &rval);if (error) { rval = error; }
fs/xfs/xfs_trace.c +1 -1
@@ -22,7 +22,6 @@#include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_da_btree.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h"
@@ -30,6 +29,7 @@#include "xfs_inode.h" #include "xfs_btree.h" #include "xfs_mount.h" +#include "xfs_da_btree.h" #include "xfs_ialloc.h" #include "xfs_itable.h" #include "xfs_alloc.h"
Signature · 6 lines
1.7.10.4 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
PATCH 17/21 xfs: add CRCs to attr leaf blocks
In reply to Dave ChinnerFrom: Dave Chinner <[email protected]>
--- fs/xfs/xfs_attr.c | 125 ++-- fs/xfs/xfs_attr_leaf.c | 1739 +++++++++++++++++++++++++++--------------------- fs/xfs/xfs_attr_leaf.h | 122 +++- fs/xfs/xfs_da_btree.c | 34 +- fs/xfs/xfs_da_btree.h | 5 +- 5 files changed, 1177 insertions(+), 848 deletions(-)
fs/xfs/xfs_attr.c +69 -56
@@ -819,7 +819,7 @@ xfs_attr_inactive(xfs_inode_t *dp) error =0 ; goto out; } - error =xfs_attr_root_inactive (&trans, dp); + error =xfs_attr3_root_inactive (&trans, dp);if (error) goto out;
@@ -905,7 +905,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)*/ dp = args->dp; args->blkno =0 ; - error =xfs_attr_leaf_read (args->trans, args->dp, args->blkno,-1 , &bp); + error =xfs_attr3_leaf_read (args->trans, args->dp, args->blkno,-1 , &bp);if (error)return error;
@@ -913,14 +913,14 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)* Look up the given attribute in the leaf block. Figure out if * the given flags produce an error or call for an atomic rename. */ - retval =xfs_attr_leaf_lookup_int (bp, args); + retval =xfs_attr3_leaf_lookup_int (bp, args);if ((args->flags &ATTR_REPLACE ) && (retval ==ENOATTR )) {xfs_trans_brelse (args->trans, bp); -return (retval); +return retval; }else if (retval ==EEXIST ) {if (args->flags &ATTR_CREATE ) {/* pure create op */ xfs_trans_brelse (args->trans, bp); -return (retval); +return retval; }trace_xfs_attr_leaf_replace (args);
@@ -936,7 +936,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)* Add the attribute to the leaf block, transitioning to a Btree * if required. */ - retval =xfs_attr_leaf_add (bp, args); + retval =xfs_attr3_leaf_add (bp, args);if (retval ==ENOSPC ) {/* * Promote the attribute list to the Btree format, then
@@ -944,7 +944,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)* can manage its own transactions. */ xfs_bmap_init (args->flist, args->firstblock); - error =xfs_attr_leaf_to_node (args); + error =xfs_attr3_leaf_to_node (args);if (!error) { error =xfs_bmap_finish (&args->trans, args->flist, &committed);
@@ -1009,7 +1009,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)* In a separate transaction, set the incomplete flag on the * "old" attr and clear the incomplete flag on the "new" attr. */ - error =xfs_attr_leaf_flipflags (args); + error =xfs_attr3_leaf_flipflags (args);if (error)return (error);
@@ -1031,19 +1031,19 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)* Read in the block containing the "old" attr, then * remove the "old" attr from that block (neat, huh!) */ - error =xfs_attr_leaf_read (args->trans, args->dp, args->blkno, + error =xfs_attr3_leaf_read (args->trans, args->dp, args->blkno,-1 , &bp);if (error)return error; -xfs_attr_leaf_remove (bp, args); +xfs_attr3_leaf_remove (bp, args);/* * If the result is small enough, shrink it all into the inode. */ if ((forkoff =xfs_attr_shortform_allfit (bp, dp))) {xfs_bmap_init (args->flist, args->firstblock); - error =xfs_attr_leaf_to_shortform (bp, args, forkoff); + error =xfs_attr3_leaf_to_shortform (bp, args, forkoff);/* bp is gone due to xfs_da_shrink_inode */ if (!error) { error = xfs_bmap_finish(&args->trans,
@@ -1075,9 +1075,9 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)/* * Added a "remote" value, just clear the incomplete flag. */ - error =xfs_attr_leaf_clearflag (args); + error =xfs_attr3_leaf_clearflag (args); } -return (error); +return error; }/*
@@ -1100,24 +1100,24 @@ xfs_attr_leaf_removename(xfs_da_args_t *args)*/ dp = args->dp; args->blkno =0 ; - error =xfs_attr_leaf_read (args->trans, args->dp, args->blkno,-1 , &bp); + error =xfs_attr3_leaf_read (args->trans, args->dp, args->blkno,-1 , &bp);if (error)return error; - error =xfs_attr_leaf_lookup_int (bp, args); + error =xfs_attr3_leaf_lookup_int (bp, args);if (error ==ENOATTR ) {xfs_trans_brelse (args->trans, bp); -return (error); +return error; } -xfs_attr_leaf_remove (bp, args); +xfs_attr3_leaf_remove (bp, args);/* * If the result is small enough, shrink it all into the inode. */ if ((forkoff =xfs_attr_shortform_allfit (bp, dp))) {xfs_bmap_init (args->flist, args->firstblock); - error =xfs_attr_leaf_to_shortform (bp, args, forkoff); + error =xfs_attr3_leaf_to_shortform (bp, args, forkoff);/* bp is gone due to xfs_da_shrink_inode */ if (!error) { error = xfs_bmap_finish(&args->trans, args->flist,
@@ -1127,7 +1127,7 @@ xfs_attr_leaf_removename(xfs_da_args_t *args)ASSERT (committed); args->trans =NULL ;xfs_bmap_cancel (args->flist); -return (error); +return error; }/*
@@ -1137,7 +1137,7 @@ xfs_attr_leaf_removename(xfs_da_args_t *args)if (committed)xfs_trans_ijoin (args->trans, dp,0 ); } -return (0 ); +return 0 ; }/*
@@ -1155,21 +1155,21 @@ xfs_attr_leaf_get(xfs_da_args_t *args)trace_xfs_attr_leaf_get (args); args->blkno =0 ; - error =xfs_attr_leaf_read (args->trans, args->dp, args->blkno,-1 , &bp); + error =xfs_attr3_leaf_read (args->trans, args->dp, args->blkno,-1 , &bp);if (error)return error; - error =xfs_attr_leaf_lookup_int (bp, args); + error =xfs_attr3_leaf_lookup_int (bp, args);if (error !=EEXIST ) {xfs_trans_brelse (args->trans, bp); -return (error); +return error; } - error =xfs_attr_leaf_getvalue (bp, args); + error =xfs_attr3_leaf_getvalue (bp, args);xfs_trans_brelse (args->trans, bp);if (!error && (args->rmtblkno >0 ) && !(args->flags &ATTR_KERNOVAL )) { error =xfs_attr_rmtval_get (args); } -return (error); +return error; }/*
@@ -1184,11 +1184,11 @@ xfs_attr_leaf_list(xfs_attr_list_context_t *context)trace_xfs_attr_leaf_list (context); context->cursor->blkno =0 ; - error =xfs_attr_leaf_read (NULL , context->dp,0 ,-1 , &bp); + error =xfs_attr3_leaf_read (NULL , context->dp,0 ,-1 , &bp);if (error)return XFS_ERROR (error); - error =xfs_attr_leaf_list_int (bp, context); + error =xfs_attr3_leaf_list_int (bp, context);xfs_trans_brelse (NULL , bp);return XFS_ERROR (error); }
@@ -1257,7 +1257,7 @@ restart: args->rmtblkcnt =0 ; } - retval =xfs_attr_leaf_add (blk->bp, state->args); + retval =xfs_attr3_leaf_add (blk->bp, state->args);if (retval ==ENOSPC ) {if (state->path.active ==1 ) {/*
@@ -1267,7 +1267,7 @@ restart:*/ xfs_da_state_free (state);xfs_bmap_init (args->flist, args->firstblock); - error =xfs_attr_leaf_to_node (args); + error =xfs_attr3_leaf_to_node (args);if (!error) { error = xfs_bmap_finish(&args->trans, args->flist,
@@ -1369,7 +1369,7 @@ restart:* In a separate transaction, set the incomplete flag on the * "old" attr and clear the incomplete flag on the "new" attr. */ - error =xfs_attr_leaf_flipflags (args); + error =xfs_attr3_leaf_flipflags (args);if (error) goto out;
@@ -1408,7 +1408,7 @@ restart:*/ blk = &state->path.blk[ state->path.active-1 ];ASSERT (blk->magic ==XFS_ATTR_LEAF_MAGIC ); - error =xfs_attr_leaf_remove (blk->bp, args); + error =xfs_attr3_leaf_remove (blk->bp, args);xfs_da3_fixhashpath (state, &state->path);/*
@@ -1449,7 +1449,7 @@ restart:/* * Added a "remote" value, just clear the incomplete flag. */ - error =xfs_attr_leaf_clearflag (args); + error =xfs_attr3_leaf_clearflag (args);if (error) goto out; }
@@ -1523,7 +1523,7 @@ xfs_attr_node_removename(xfs_da_args_t *args)* Mark the attribute as INCOMPLETE, then bunmapi() the * remote value. */ - error =xfs_attr_leaf_setflag (args); + error =xfs_attr3_leaf_setflag (args);if (error) goto out; error =xfs_attr_rmtval_remove (args);
@@ -1544,7 +1544,7 @@ xfs_attr_node_removename(xfs_da_args_t *args)*/ blk = &state->path.blk[ state->path.active-1 ];ASSERT (blk->magic ==XFS_ATTR_LEAF_MAGIC ); - retval =xfs_attr_leaf_remove (blk->bp, args); + retval =xfs_attr3_leaf_remove (blk->bp, args);xfs_da3_fixhashpath (state, &state->path);/*
@@ -1590,13 +1590,13 @@ xfs_attr_node_removename(xfs_da_args_t *args)ASSERT (state->path.blk[0 ].bp); state->path.blk[0 ].bp =NULL ; - error =xfs_attr_leaf_read (args->trans, args->dp,0 ,-1 , &bp); + error =xfs_attr3_leaf_read (args->trans, args->dp,0 ,-1 , &bp);if (error) goto out;if ((forkoff =xfs_attr_shortform_allfit (bp, dp))) {xfs_bmap_init (args->flist, args->firstblock); - error =xfs_attr_leaf_to_shortform (bp, args, forkoff); + error =xfs_attr3_leaf_to_shortform (bp, args, forkoff);/* bp is gone due to xfs_da_shrink_inode */ if (!error) { error = xfs_bmap_finish(&args->trans,
@@ -1768,7 +1768,7 @@ xfs_attr_node_get(xfs_da_args_t *args)/* * Get the value, local or "remote" */ - retval =xfs_attr_leaf_getvalue (blk->bp, args); + retval =xfs_attr3_leaf_getvalue (blk->bp, args);if (!retval && (args->rmtblkno >0 ) && !(args->flags &ATTR_KERNOVAL )) { retval =xfs_attr_rmtval_get (args);
@@ -1793,7 +1793,9 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)attrlist_cursor_kern_t *cursor;xfs_attr_leafblock_t *leaf;xfs_da_intnode_t *node; -xfs_da_node_entry_t *btree; +struct xfs_attr3_icleaf_hdr leafhdr; +struct xfs_da3_icnode_hdr nodehdr; +struct xfs_da_node_entry *btree;int error, i;struct xfs_buf *bp;
@@ -1814,22 +1816,28 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)if ((error !=0 ) && (error !=EFSCORRUPTED ))return (error);if (bp) { +struct xfs_attr_leaf_entry *entries; + node = bp->b_addr;switch (be16_to_cpu (node->hdr.info.magic)) {case XFS_DA_NODE_MAGIC : +case XFS_DA3_NODE_MAGIC :trace_xfs_attr_list_wrong_blk (context);xfs_trans_brelse (NULL , bp); bp =NULL ;break ;case XFS_ATTR_LEAF_MAGIC : +case XFS_ATTR3_LEAF_MAGIC : leaf = bp->b_addr; -if (cursor->hashval >be32_to_cpu (leaf->entries[ -be16_to_cpu (leaf->hdr.count)-1 ].hashval)) { +xfs_attr3_leaf_hdr_from_disk (&leafhdr, leaf); + entries =xfs_attr3_leaf_entryp (leaf); +if (cursor->hashval >be32_to_cpu ( + entries[leafhdr.count -1 ].hashval)) {trace_xfs_attr_list_wrong_blk (context);xfs_trans_brelse (NULL , bp); bp =NULL ; - }else if (cursor->hashval <= -be32_to_cpu (leaf->entries[0 ].hashval)) { + }else if (cursor->hashval <=be32_to_cpu ( + entries[0 ].hashval)) {trace_xfs_attr_list_wrong_blk (context);xfs_trans_brelse (NULL , bp); bp =NULL ;
@@ -1851,27 +1859,31 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)if (bp ==NULL ) { cursor->blkno =0 ;for (;;) { +__uint16_t magic; + error =xfs_da3_node_read (NULL , context->dp, cursor->blkno,-1 , &bp,XFS_ATTR_FORK );if (error)return (error); node = bp->b_addr; -if (node->hdr.info.magic == -cpu_to_be16 (XFS_ATTR_LEAF_MAGIC )) + magic =be16_to_cpu (node->hdr.info.magic); +if (magic ==XFS_ATTR_LEAF_MAGIC || + magic ==XFS_ATTR3_LEAF_MAGIC )break ; -if (unlikely (node->hdr.info.magic != -cpu_to_be16 (XFS_DA_NODE_MAGIC ))) { +if (magic !=XFS_DA_NODE_MAGIC && + magic !=XFS_DA3_NODE_MAGIC ) {XFS_CORRUPTION_ERROR ("xfs_attr_node_list(3)" ,XFS_ERRLEVEL_LOW , context->dp->i_mount, node);xfs_trans_brelse (NULL , bp); -return (XFS_ERROR (EFSCORRUPTED )); +return XFS_ERROR (EFSCORRUPTED ); } + +xfs_da3_node_hdr_from_disk (&nodehdr, node); btree =xfs_da3_node_tree_p (node); -for (i =0 ; i <be16_to_cpu (node->hdr.count); - btree++, i++) { +for (i =0 ; i < nodehdr.count; btree++, i++) {if (cursor->hashval <=be32_to_cpu (btree->hashval)) { cursor->blkno =be32_to_cpu (btree->before);
@@ -1880,9 +1892,9 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)break ; } } -if (i ==be16_to_cpu (node->hdr.count)) { +if (i == nodehdr.count) {xfs_trans_brelse (NULL , bp); -return (0 ); +return 0 ; }xfs_trans_brelse (NULL , bp); }
@@ -1896,22 +1908,23 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)*/ for (;;) { leaf = bp->b_addr; - error =xfs_attr_leaf_list_int (bp, context); + error =xfs_attr3_leaf_list_int (bp, context);if (error) {xfs_trans_brelse (NULL , bp);return error; } -if (context->seen_enough || leaf->hdr.info.forw ==0 ) +xfs_attr3_leaf_hdr_from_disk (&leafhdr, leaf); +if (context->seen_enough || leafhdr.forw ==0 )break ; - cursor->blkno =be32_to_cpu (leaf->hdr.info.forw); + cursor->blkno = leafhdr.forw;xfs_trans_brelse (NULL , bp); - error =xfs_attr_leaf_read (NULL , context->dp, cursor->blkno,-1 , + error =xfs_attr3_leaf_read (NULL , context->dp, cursor->blkno,-1 , &bp);if (error)return error; }xfs_trans_brelse (NULL , bp); -return (0 ); +return 0 ; }
fs/xfs/xfs_attr_leaf.c +990 -749
2,628 lines not on this page · raw message
fs/xfs/xfs_attr_leaf.h +95 -27
122 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
Signature · 6 lines
1.7.10.4 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Part of the diff is not shown here. View the raw message.
PATCH 18/21 xfs: split remote attribute code out
In reply to Dave ChinnerFrom: Dave Chinner <[email protected]>
Adding CRC support to remote attributes adds a significant amount of remote attribute specific code. Split the existing remote attribute code out into it's own file so that all the relevant remote attribute code is in a single, easy to find place.
--- fs/xfs/Makefile | 1 + fs/xfs/xfs_attr.c | 298 +---------------------------------------- fs/xfs/xfs_attr.h | 1 - fs/xfs/xfs_attr_leaf.c | 1 + fs/xfs/xfs_attr_remote.c | 328 ++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_attr_remote.h | 25 ++++ 6 files changed, 356 insertions(+), 298 deletions(-) create mode 100644 fs/xfs/xfs_attr_remote.c create mode 100644 fs/xfs/xfs_attr_remote.h
fs/xfs/Makefile +1 -0
@@ -58,6 +58,7 @@ xfs-y += xfs_alloc.o \ xfs_alloc_btree.o \ xfs_attr.o \ xfs_attr_leaf.o \ + xfs_attr_remote.o \ xfs_bmap.o \ xfs_bmap_btree.o \ xfs_btree.o \
fs/xfs/xfs_attr.c +1 -297
313 lines not on this page · raw message
fs/xfs/xfs_attr.h +0 -1
@@ -140,7 +140,6 @@ typedef struct xfs_attr_list_context {* Overall external interface routines. */ int xfs_attr_inactive (struct xfs_inode *dp); -int xfs_attr_rmtval_get (struct xfs_da_args *args);int xfs_attr_list_int (struct xfs_attr_list_context *);#endif /* __XFS_ATTR_H__ */
fs/xfs/xfs_attr_leaf.c +1 -0
@@ -32,6 +32,7 @@#include "xfs_alloc.h" #include "xfs_btree.h" #include "xfs_attr_sf.h" +#include "xfs_attr_remote.h" #include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_inode_item.h"
fs/xfs/xfs_attr_remote.c new file +328 -0
328 lines not on this page · raw message
fs/xfs/xfs_attr_remote.h new file +25 -0
@@ -0,0 +1,25 @@ +/* +* 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_ATTR_REMOTE_H__ +#define __XFS_ATTR_REMOTE_H__ + +int xfs_attr_rmtval_get (struct xfs_da_args *args); +int xfs_attr_rmtval_set (struct xfs_da_args *args); +int xfs_attr_rmtval_remove (struct xfs_da_args *args); + +#endif /* __XFS_ATTR_REMOTE_H__ */
Signature · 6 lines
1.7.10.4 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
PATCH 19/21 xfs: add CRC protection to remote attributes
In reply to Dave ChinnerFrom: Dave Chinner <[email protected]>
There are two ways of doing this - the first is to add a CRC to the remote attribute entry in the attribute block. The second is to treat them similar to the remote symlink, where each fragment has it's own header and identifies fragment location in the attribute.
The problem with the CRC in the remote attr entry is that we cannot identify the owner of the metadata from the metadata blocks themselves, or where the blocks fit into the remote attribute. The down side to this approach is that we never know when the attribute has been read from disk or not and so we have to verify it every time it is read, and we must calculate it during the create transaction and log it. We do not log CRCs for any other metadata, and so this creates a unique set of coherency problems that, in general, are best avoided.
Adding an identifying header to each allocated block allows us to identify each fragment and where in the attribute it is located. It enables us to rebuild the remote attribute from just the raw blocks containing the attribute. It also provides us to do per-block CRCs verification at IO time rather than during the transaction context that creates it or every time it is read into a user buffer. Hence it avoids all the problems that an external, logged CRC has, and provides all the benefits of self identifying metadata.
The only complexity is that we have to add a header per fragment, and we don't know how many fragments will be needed prior to allocations. If we take the symlink example, the header is 56 bytes and hence for a 4k block size filesystem, in the worst case 16 headers requires 1 extra block for the 64k attribute data. For 512 byte filesystems the worst case is an extra block for every 9 fragments (i.e. 16 extra blocks in the worse case). This will be very rare and so it's not really a major concern.
Because allocation is done in two steps - the first finds a hole large enough in the attribute file, the second does the allocation - we only need to find a hole big enough for a worst case allocation. We only need to allocate enough extra blocks for number of headers required by the fragments, and we can calculate that as we go....
Hence it really only makes sense to use the same model as for symlinks - it doesn't add that much complexity, does not require an attribute tree format change, and does not require logging calculated CRC values.
--- fs/xfs/xfs_attr_remote.c | 324 ++++++++++++++++++++++++++++++++++++++-------- fs/xfs/xfs_attr_remote.h | 19 +++ 2 files changed, 292 insertions(+), 51 deletions(-)
fs/xfs/xfs_attr_remote.c +273 -51
@@ -1,5 +1,6 @@/* * 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
@@ -37,63 +38,232 @@#include "xfs_attr_remote.h" #include "xfs_trans_space.h" #include "xfs_trace.h" - +#include "xfs_cksum.h" +#include "xfs_buf_item.h" #define ATTR_RMTVALUE_MAPSIZE 1/* # of map entries at once */ /* +* Each contiguous block has a header, so it is not just a simple attribute +* length to FSB conversion. +*/ +static int +xfs_attr3_rmt_blocks ( +struct xfs_mount *mp, +int attrlen) +{ +int fsblocks =0 ; +int len = attrlen; + +do { + fsblocks++; + len -=XFS_ATTR3_RMT_BUF_SPACE (mp, mp->m_sb.sb_blocksize); + }while (len >0 ); + +return fsblocks; +} + +static bool +xfs_attr3_rmt_verify ( +struct xfs_buf *bp) +{ +struct xfs_mount *mp = bp->b_target->bt_mount; +struct xfs_attr3_rmt_hdr *rmt = bp->b_addr; + +if (!xfs_sb_version_hascrc (&mp->m_sb)) +return false; +if (rmt->rm_magic !=cpu_to_be32 (XFS_ATTR3_RMT_MAGIC )) +return false; +if (!uuid_equal (&rmt->rm_uuid, &mp->m_sb.sb_uuid)) +return false; +if (bp->b_bn !=be64_to_cpu (rmt->rm_blkno)) +return false; +if (be32_to_cpu (rmt->rm_offset) + +be32_to_cpu (rmt->rm_bytes) >=MAXPATHLEN ) +return false; +if (rmt->rm_owner ==0 ) +return false; + +return true; +} + +static void +xfs_attr3_rmt_read_verify ( +struct xfs_buf *bp) +{ +struct xfs_mount *mp = bp->b_target->bt_mount; + +/* no verification of non-crc buffers */ +if (!xfs_sb_version_hascrc (&mp->m_sb)) +return ; + +if (!xfs_verify_cksum (bp->b_addr,BBTOB (bp->b_length), +XFS_ATTR3_RMT_CRC_OFF ) || + !xfs_attr3_rmt_verify (bp)) { +XFS_CORRUPTION_ERROR (__func__,XFS_ERRLEVEL_LOW , mp, bp->b_addr); +xfs_buf_ioerror (bp,EFSCORRUPTED ); + } +} + +static void +xfs_attr3_rmt_write_verify ( +struct xfs_buf *bp) +{ +struct xfs_mount *mp = bp->b_target->bt_mount; +struct xfs_buf_log_item *bip = bp->b_fspriv; + +/* no verification of non-crc buffers */ +if (!xfs_sb_version_hascrc (&mp->m_sb)) +return ; + +if (!xfs_attr3_rmt_verify (bp)) { +XFS_CORRUPTION_ERROR (__func__,XFS_ERRLEVEL_LOW , mp, bp->b_addr); +xfs_buf_ioerror (bp,EFSCORRUPTED ); +return ; + } + +if (bip) { +struct xfs_attr3_rmt_hdr *rmt = bp->b_addr; + rmt->rm_lsn =cpu_to_be64 (bip->bli_item.li_lsn); + } +xfs_update_cksum (bp->b_addr,BBTOB (bp->b_length), +XFS_ATTR3_RMT_CRC_OFF ); +} + +const struct xfs_buf_ops xfs_attr3_rmt_buf_ops = { + .verify_read = xfs_attr3_rmt_read_verify, + .verify_write = xfs_attr3_rmt_write_verify, +}; + +static int +xfs_attr3_rmt_hdr_set ( +struct xfs_mount *mp, +xfs_ino_t ino, +uint32_t offset, +uint32_t size, +struct xfs_buf *bp) +{ +struct xfs_attr3_rmt_hdr *rmt = bp->b_addr; + +if (!xfs_sb_version_hascrc (&mp->m_sb)) +return 0 ; + + rmt->rm_magic =cpu_to_be32 (XFS_ATTR3_RMT_MAGIC ); + rmt->rm_offset =cpu_to_be32 (offset); + rmt->rm_bytes =cpu_to_be32 (size); +uuid_copy (&rmt->rm_uuid, &mp->m_sb.sb_uuid); + rmt->rm_owner =cpu_to_be64 (ino); + rmt->rm_blkno =cpu_to_be64 (bp->b_bn); + bp->b_ops = &xfs_attr3_rmt_buf_ops; + +return sizeof (struct xfs_attr3_rmt_hdr ); +} + +/* +* Checking of the remote attribute header is split into two parts. the verifier +* does CRC, location and bounds checking, the unpacking function checks the +* attribute parameters and owner. +*/ +static bool +xfs_attr3_rmt_hdr_ok ( +struct xfs_mount *mp, +xfs_ino_t ino, +uint32_t offset, +uint32_t size, +struct xfs_buf *bp) +{ +struct xfs_attr3_rmt_hdr *rmt = bp->b_addr; + +if (offset !=be32_to_cpu (rmt->rm_offset)) +return false; +if (size !=be32_to_cpu (rmt->rm_bytes)) +return false; +if (ino !=be64_to_cpu (rmt->rm_owner)) +return false; + +/* ok */ +return true; + +} + +/* * Read the value associated with an attribute from the out-of-line buffer * that we stored it in. */ int -xfs_attr_rmtval_get (xfs_da_args_t *args) +xfs_attr_rmtval_get ( +struct xfs_da_args *args) { -xfs_bmbt_irec_t map[ATTR_RMTVALUE_MAPSIZE ]; -xfs_mount_t *mp; -xfs_daddr_t dblkno; -void *dst; -xfs_buf_t *bp; -int nmap, error, tmp, valuelen, blkcnt, i; -xfs_dablk_t lblkno; +struct xfs_bmbt_irec map[ATTR_RMTVALUE_MAPSIZE ]; +struct xfs_mount *mp = args->dp->i_mount; +struct xfs_buf *bp; +xfs_daddr_t dblkno; +xfs_dablk_t lblkno = args->rmtblkno; +void *dst = args->value; +int valuelen = args->valuelen; +int nmap; +int error; +int blkcnt; +int i; +int offset =0 ;trace_xfs_attr_rmtval_get (args);ASSERT (!(args->flags &ATTR_KERNOVAL )); - mp = args->dp->i_mount; - dst = args->value; - valuelen = args->valuelen; - lblkno = args->rmtblkno;while (valuelen >0 ) { nmap =ATTR_RMTVALUE_MAPSIZE ; error =xfs_bmapi_read (args->dp, (xfs_fileoff_t )lblkno, args->rmtblkcnt, map, &nmap,XFS_BMAPI_ATTRFORK );if (error) -return (error); +return error;ASSERT (nmap >=1 );for (i =0 ; (i < nmap) && (valuelen >0 ); i++) { +int byte_cnt; +char *src; +ASSERT ((map[i].br_startblock !=DELAYSTARTBLOCK ) && (map[i].br_startblock !=HOLESTARTBLOCK )); dblkno =XFS_FSB_TO_DADDR (mp, map[i].br_startblock); blkcnt =XFS_FSB_TO_BB (mp, map[i].br_blockcount); error =xfs_trans_read_buf (mp,NULL , mp->m_ddev_targp, - dblkno, blkcnt,0 , &bp,NULL ); + dblkno, blkcnt,0 , &bp, + &xfs_attr3_rmt_buf_ops);if (error) -return (error); +return error; + + byte_cnt =min_t (int, valuelen,BBTOB (bp->b_length)); + byte_cnt =XFS_ATTR3_RMT_BUF_SPACE (mp, byte_cnt); - tmp =min_t (int, valuelen,BBTOB (bp->b_length)); -xfs_buf_iomove (bp,0 , tmp, dst,XBRW_READ ); + src = bp->b_addr; +if (xfs_sb_version_hascrc (&mp->m_sb)) { +if (!xfs_attr3_rmt_hdr_ok (mp, args->dp->i_ino, + offset, byte_cnt, bp)) { +xfs_alert (mp, +"remote attribute header does not match required off/len/owner (0x%x/Ox%x,0x%llx)" , + offset, byte_cnt, args->dp->i_ino); +xfs_buf_relse (bp); +return EFSCORRUPTED ; + + } + + src +=sizeof (struct xfs_attr3_rmt_hdr ); + } + +memcpy (dst, src, byte_cnt);xfs_buf_relse (bp); - dst += tmp; - valuelen -= tmp; + + offset += byte_cnt; + dst += byte_cnt; + valuelen -= byte_cnt; lblkno += map[i].br_blockcount; } }ASSERT (valuelen ==0 ); -return (0 ); +return 0 ; }/*
@@ -101,35 +271,49 @@ xfs_attr_rmtval_get(xfs_da_args_t *args)* that we have defined for it. */ STATIC int -xfs_attr_rmtval_set (xfs_da_args_t *args) +xfs_attr_rmtval_set ( +struct xfs_da_args *args) { -xfs_mount_t *mp; -xfs_fileoff_t lfileoff; -xfs_inode_t *dp; -xfs_bmbt_irec_t map; -xfs_daddr_t dblkno; -void *src; -xfs_buf_t *bp; -xfs_dablk_t lblkno; -int blkcnt, valuelen, nmap, error, tmp, committed; +struct xfs_inode *dp = args->dp; +struct xfs_mount *mp = dp->i_mount; +struct xfs_bmbt_irec map; +struct xfs_buf *bp; +xfs_daddr_t dblkno; +xfs_dablk_t lblkno; +xfs_fileoff_t lfileoff =0 ; +void *src = args->value; +int blkcnt; +int valuelen; +int nmap; +int error; +int hdrcnt =0 ; +bool crcs =xfs_sb_version_hascrc (&mp->m_sb); +int offset =0 ;trace_xfs_attr_rmtval_set (args); - dp = args->dp; - mp = dp->i_mount; - src = args->value; -/* * Find a "hole" in the attribute address space large enough for -* us to drop the new attribute's value into. +* us to drop the new attribute's value into. Because CRC enable +* attributes have headers, we can't just do a straight byte to FSB +* conversion. We calculate the worst case block count in this case +* and we may not need that many, so we have to handle this when +* allocating the blocks below. */ - blkcnt =XFS_B_TO_FSB (mp, args->valuelen); - lfileoff =0 ; +if (!crcs) + blkcnt =XFS_B_TO_FSB (mp, args->valuelen); +else + blkcnt =xfs_attr3_rmt_blocks (mp, args->valuelen); + error =xfs_bmap_first_unused (args->trans, args->dp, blkcnt, &lfileoff,XFS_ATTR_FORK ); -if (error) { -return (error); - } +if (error) +return error; + +/* Start with the attribute data. We'll allocate the rest afterwards. */ +if (crcs) + blkcnt =XFS_B_TO_FSB (mp, args->valuelen); + args->rmtblkno = lblkno = (xfs_dablk_t )lfileoff; args->rmtblkcnt = blkcnt;
@@ -137,6 +321,8 @@ xfs_attr_rmtval_set(xfs_da_args_t *args)* Roll through the "value", allocating blocks on disk as required. */ while (blkcnt >0 ) { +int committed; +/* * Allocate a single extent, up to the size of the value. */
@@ -170,6 +356,27 @@ xfs_attr_rmtval_set(xfs_da_args_t *args) (map.br_startblock != HOLESTARTBLOCK)); lblkno += map.br_blockcount; blkcnt -= map.br_blockcount; + hdrcnt++; + +/* +* If we have enough blocks for the attribute data, calculate +* how many extra blocks we need for headers. We might run +* through this multiple times in the case that the additional +* headers in the blocks needed for the data fragments spills +* into requiring more blocks. e.g. for 512 byte blocks, we'll +* spill for another block every 9 headers we require in this +* loop. +*/ + +if (crcs && blkcnt ==0 ) { +int total_len; + + total_len = args->valuelen + + hdrcnt *sizeof (struct xfs_attr3_rmt_hdr ); + blkcnt =XFS_B_TO_FSB (mp, total_len); + blkcnt -= args->rmtblkcnt; + args->rmtblkcnt += blkcnt; + }/* * Start the next trans in the chain.
@@ -188,7 +395,8 @@ xfs_attr_rmtval_set(xfs_da_args_t *args) lblkno = args->rmtblkno; valuelen = args->valuelen;while (valuelen >0 ) { -int buflen; +int byte_cnt; +char *buf;/* * Try to remember where we decided to put the value.
@@ -210,24 +418,38 @@ xfs_attr_rmtval_set(xfs_da_args_t *args) bp =xfs_buf_get (mp->m_ddev_targp, dblkno, blkcnt,0 );if (!bp)return ENOMEM ; + bp->b_ops = &xfs_attr3_rmt_buf_ops; + + byte_cnt =BBTOB (bp->b_length); + byte_cnt =XFS_ATTR3_RMT_BUF_SPACE (mp, byte_cnt); +if (valuelen < byte_cnt) { + byte_cnt = valuelen; + } + + buf = bp->b_addr; + buf +=xfs_attr3_rmt_hdr_set (mp, dp->i_ino, offset, + byte_cnt, bp); +memcpy (buf, src, byte_cnt); - buflen =BBTOB (bp->b_length); - tmp =min_t (int, valuelen, buflen); -xfs_buf_iomove (bp,0 , tmp, src,XBRW_WRITE ); -if (tmp < buflen) -xfs_buf_zero (bp, tmp, buflen - tmp); +if (byte_cnt <BBTOB (bp->b_length)) +xfs_buf_zero (bp, byte_cnt, +BBTOB (bp->b_length) - byte_cnt); error =xfs_bwrite (bp);/* GROT: NOTE: synchronous write */ xfs_buf_relse (bp);if (error)return error; - src += tmp; - valuelen -= tmp; + + src += byte_cnt; + valuelen -= byte_cnt; + offset += byte_cnt; + hdrcnt--; lblkno += map.br_blockcount; }ASSERT (valuelen ==0 ); -return (0 ); +ASSERT (hdrcnt ==0 ); +return 0 ; }/*
@@ -306,7 +528,7 @@ xfs_attr_rmtval_remove(xfs_da_args_t *args)ASSERT (committed); args->trans =NULL ;xfs_bmap_cancel (args->flist); -return (error); +return error; }/*
fs/xfs/xfs_attr_remote.h +19 -0
@@ -18,6 +18,25 @@#ifndef __XFS_ATTR_REMOTE_H__#define __XFS_ATTR_REMOTE_H__ +#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)) +int xfs_attr_rmtval_get (struct xfs_da_args *args);int xfs_attr_rmtval_set (struct xfs_da_args *args);int xfs_attr_rmtval_remove (struct xfs_da_args *args);
Signature · 6 lines
1.7.10.4 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
PATCH 20/21 xfs: add buffer types to directory and attribute buffers
In reply to Dave ChinnerFrom: Dave Chinner <[email protected]>
Add buffer types to the buffer log items so that log recovery can validate the buffers and calculate CRCs correctly after the buffers are recovered.
--- fs/xfs/xfs_attr_leaf.c | 9 +- fs/xfs/xfs_attr_remote.h | 2 + fs/xfs/xfs_buf_item.h | 18 +++- fs/xfs/xfs_da_btree.c | 46 +++++++- fs/xfs/xfs_da_btree.h | 2 + fs/xfs/xfs_dir2_block.c | 12 ++- fs/xfs/xfs_dir2_data.c | 8 +- fs/xfs/xfs_dir2_leaf.c | 26 ++++- fs/xfs/xfs_dir2_node.c | 15 ++- fs/xfs/xfs_dir2_priv.h | 2 + fs/xfs/xfs_log_recover.c | 259 ++++++++++++++++++++++++++++++++-------------- fs/xfs/xfs_trans.h | 2 + fs/xfs/xfs_trans_buf.c | 17 +++ 13 files changed, 323 insertions(+), 95 deletions(-)
fs/xfs/xfs_attr_leaf.c +8 -1
@@ -271,8 +271,13 @@ xfs_attr3_leaf_read(xfs_daddr_t mappedbno, struct xfs_buf **bpp) { - return xfs_da_read_buf(tp, dp, bno, mappedbno, bpp, + int err; + + err =xfs_da_read_buf (tp, dp, bno, mappedbno, bpp,XFS_ATTR_FORK , &xfs_attr3_leaf_buf_ops); +if (!err && tp) +xfs_trans_buf_set_type (tp, *bpp,XFS_BLF_ATTR_LEAF_BUF ); +return err; }/*========================================================================
@@ -1078,6 +1083,7 @@ xfs_attr3_leaf_to_node( goto out;/* copy leaf to new buffer, update identifiers */ +xfs_trans_buf_set_type (args->trans, bp2,XFS_BLF_ATTR_LEAF_BUF ); bp2->b_ops = bp1->b_ops;memcpy (bp2->b_addr, bp1->b_addr,XFS_LBSIZE (mp));if (xfs_sb_version_hascrc (&mp->m_sb)) {
@@ -1140,6 +1146,7 @@ xfs_attr3_leaf_create(if (error)return error; bp->b_ops = &xfs_attr3_leaf_buf_ops; +xfs_trans_buf_set_type (args->trans, bp,XFS_BLF_ATTR_LEAF_BUF ); leaf = bp->b_addr;memset (leaf,0 ,XFS_LBSIZE (mp));
fs/xfs/xfs_attr_remote.h +2 -0
@@ -37,6 +37,8 @@ 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_attr_rmtval_get (struct xfs_da_args *args);int xfs_attr_rmtval_set (struct xfs_da_args *args);int xfs_attr_rmtval_remove (struct xfs_da_args *args);
fs/xfs/xfs_buf_item.h +17 -1
@@ -50,6 +50,14 @@ extern kmem_zone_t *xfs_buf_item_zone;#define XFS_BLF_AGI_BUF (1<<8)#define XFS_BLF_DINO_BUF (1<<9)#define XFS_BLF_SYMLINK_BUF (1<<10) +#define XFS_BLF_DIR_BLOCK_BUF (1<<11) +#define XFS_BLF_DIR_DATA_BUF (1<<12) +#define XFS_BLF_DIR_FREE_BUF (1<<13) +#define XFS_BLF_DIR_LEAF1_BUF (1<<14) +#define XFS_BLF_DIR_LEAFN_BUF (1<<15) +#define XFS_BLF_DA_NODE_BUF (1<<16) +#define XFS_BLF_ATTR_LEAF_BUF (1<<17) +#define XFS_BLF_ATTR_RMT_BUF (1<<18)#define XFS_BLF_TYPE_MASK \ (XFS_BLF_UDQUOT_BUF | \
@@ -60,7 +68,15 @@ extern kmem_zone_t *xfs_buf_item_zone; XFS_BLF_AGFL_BUF | \ XFS_BLF_AGI_BUF | \ XFS_BLF_DINO_BUF | \ - XFS_BLF_SYMLINK_BUF) + XFS_BLF_SYMLINK_BUF | \ + XFS_BLF_DIR_BLOCK_BUF | \ + XFS_BLF_DIR_DATA_BUF | \ + XFS_BLF_DIR_FREE_BUF | \ + XFS_BLF_DIR_LEAF1_BUF | \ + XFS_BLF_DIR_LEAFN_BUF | \ + XFS_BLF_DA_NODE_BUF | \ + XFS_BLF_ATTR_LEAF_BUF | \ + XFS_BLF_ATTR_RMT_BUF)#define XFS_BLF_CHUNK 128#define XFS_BLF_SHIFT 7
fs/xfs/xfs_da_btree.c +43 -3
89 lines not on this page · raw message
fs/xfs/xfs_da_btree.h +2 -0
@@ -301,6 +301,8 @@ 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. */
fs/xfs/xfs_dir2_block.c +9 -3
@@ -132,20 +132,26 @@ xfs_dir3_block_read( struct xfs_buf **bpp) {struct xfs_mount *mp = dp->i_mount; +int err; -return xfs_da_read_buf (tp, dp, mp->m_dirdatablk,-1 , bpp, + err =xfs_da_read_buf (tp, dp, mp->m_dirdatablk,-1 , bpp,XFS_DATA_FORK , &xfs_dir3_block_buf_ops); +if (!err && tp) +xfs_trans_buf_set_type (tp, *bpp,XFS_BLF_DIR_BLOCK_BUF ); +return err; }static void xfs_dir3_block_init (struct xfs_mount *mp, +struct xfs_trans *tp,struct xfs_buf *bp,struct xfs_inode *dp) {struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; bp->b_ops = &xfs_dir3_block_buf_ops; +xfs_trans_buf_set_type (tp, bp,XFS_BLF_DIR_BLOCK_BUF );if (xfs_sb_version_hascrc (&mp->m_sb)) {memset (hdr3,0 ,sizeof (*hdr3));
@@ -1080,7 +1086,7 @@ xfs_dir2_leaf_to_block(/* * Start converting it to block form. */ -xfs_dir3_block_init (mp, dbp, dp); +xfs_dir3_block_init (mp, tp, dbp, dp); needlog =1 ; needscan =0 ;
@@ -1209,7 +1215,7 @@ xfs_dir2_sf_to_block(kmem_free (sfp);return error; } -xfs_dir3_block_init (mp, bp, dp); +xfs_dir3_block_init (mp, tp, bp, dp); hdr = bp->b_addr;/*
fs/xfs/xfs_dir2_data.c +7 -1
@@ -301,8 +301,13 @@ xfs_dir3_data_read(xfs_daddr_t mapped_bno, struct xfs_buf **bpp) { - return xfs_da_read_buf(tp, dp, bno, mapped_bno, bpp, + int err; + + err =xfs_da_read_buf (tp, dp, bno, mapped_bno, bpp,XFS_DATA_FORK , &xfs_dir3_data_buf_ops); +if (!err && tp) +xfs_trans_buf_set_type (tp, *bpp,XFS_BLF_DIR_DATA_BUF ); +return err; }int
@@ -571,6 +576,7 @@ xfs_dir3_data_init(if (error)return error; bp->b_ops = &xfs_dir3_data_buf_ops; +xfs_trans_buf_set_type (tp, bp,XFS_BLF_DIR_DATA_BUF );/* * Initialize the header.
fs/xfs/xfs_dir2_leaf.c +21 -5
@@ -277,7 +277,7 @@ xfs_dir3_leafn_write_verify(__write_verify (bp,XFS_DIR2_LEAFN_MAGIC ); } -static const struct xfs_buf_ops xfs_dir3_leaf1_buf_ops = { +const struct xfs_buf_ops xfs_dir3_leaf1_buf_ops = { .verify_read = xfs_dir3_leaf1_read_verify, .verify_write = xfs_dir3_leaf1_write_verify, };
@@ -295,8 +295,13 @@ xfs_dir3_leaf_read(xfs_daddr_t mappedbno, struct xfs_buf **bpp) { - return xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp, + int err; + + err =xfs_da_read_buf (tp, dp, fbno, mappedbno, bpp,XFS_DATA_FORK , &xfs_dir3_leaf1_buf_ops); +if (!err && tp) +xfs_trans_buf_set_type (tp, *bpp,XFS_BLF_DIR_LEAF1_BUF ); +return err; }int
@@ -307,8 +312,13 @@ xfs_dir3_leafn_read(xfs_daddr_t mappedbno, struct xfs_buf **bpp) { - return xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp, + int err; + + err =xfs_da_read_buf (tp, dp, fbno, mappedbno, bpp,XFS_DATA_FORK , &xfs_dir3_leafn_buf_ops); +if (!err && tp) +xfs_trans_buf_set_type (tp, *bpp,XFS_BLF_DIR_LEAFN_BUF ); +return err; }/*
@@ -317,6 +327,7 @@ xfs_dir3_leafn_read(static void xfs_dir3_leaf_init (struct xfs_mount *mp, +struct xfs_trans *tp,struct xfs_buf *bp,xfs_ino_t owner,__uint16_t type)
@@ -351,8 +362,11 @@ xfs_dir3_leaf_init( ltp =xfs_dir2_leaf_tail_p (mp, leaf); ltp->bestcount =0 ; bp->b_ops = &xfs_dir3_leaf1_buf_ops; - }else +xfs_trans_buf_set_type (tp, bp,XFS_BLF_DIR_LEAF1_BUF ); + }else { bp->b_ops = &xfs_dir3_leafn_buf_ops; +xfs_trans_buf_set_type (tp, bp,XFS_BLF_DIR_LEAFN_BUF ); + } }int
@@ -377,7 +391,7 @@ xfs_dir3_leaf_get_buf(if (error)return error; -xfs_dir3_leaf_init (mp, bp, dp->i_ino, magic); +xfs_dir3_leaf_init (mp, tp, bp, dp->i_ino, magic);xfs_dir3_leaf_log_header (tp, bp);if (magic ==XFS_DIR2_LEAF1_MAGIC )xfs_dir3_leaf_log_tail (tp, bp);
@@ -473,6 +487,7 @@ xfs_dir2_block_to_leaf(* Fix up the block header, make it a data block. */ dbp->b_ops = &xfs_dir3_data_buf_ops; +xfs_trans_buf_set_type (tp, dbp,XFS_BLF_DIR_DATA_BUF );if (hdr->magic ==cpu_to_be32 (XFS_DIR2_BLOCK_MAGIC )) hdr->magic =cpu_to_be32 (XFS_DIR2_DATA_MAGIC );else
@@ -2181,6 +2196,7 @@ xfs_dir2_node_to_leaf(xfs_dir3_leaf_compact (args, &leafhdr, lbp); lbp->b_ops = &xfs_dir3_leaf1_buf_ops; +xfs_trans_buf_set_type (tp, lbp,XFS_BLF_DIR_LEAF1_BUF ); leafhdr.magic = (leafhdr.magic ==XFS_DIR2_LEAFN_MAGIC ) ?XFS_DIR2_LEAF1_MAGIC :XFS_DIR3_LEAFN_MAGIC ;
fs/xfs/xfs_dir2_node.c +13 -2
@@ -144,7 +144,7 @@ xfs_dir3_free_write_verify(xfs_update_cksum (bp->b_addr,BBTOB (bp->b_length),XFS_DIR3_FREE_CRC_OFF ); } -static const struct xfs_buf_ops xfs_dir3_free_buf_ops = { +const struct xfs_buf_ops xfs_dir3_free_buf_ops = { .verify_read = xfs_dir3_free_read_verify, .verify_write = xfs_dir3_free_write_verify, };
@@ -158,8 +158,15 @@ __xfs_dir3_free_read(xfs_daddr_t mappedbno, struct xfs_buf **bpp) { - return xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp, + int err; + + err =xfs_da_read_buf (tp, dp, fbno, mappedbno, bpp,XFS_DATA_FORK , &xfs_dir3_free_buf_ops); + +/* try read returns without an error or *bpp if it lands in a hole */ +if (!err && tp && *bpp) +xfs_trans_buf_set_type (tp, *bpp,XFS_BLF_DIR_FREE_BUF ); +return err; }int
@@ -246,6 +253,7 @@ xfs_dir3_free_get_buf(if (error)return error; +xfs_trans_buf_set_type (tp, bp,XFS_BLF_DIR_FREE_BUF ); bp->b_ops = &xfs_dir3_free_buf_ops;;/*
@@ -394,6 +402,7 @@ xfs_dir2_leaf_to_node(else leaf->hdr.info.magic =cpu_to_be16 (XFS_DIR3_LEAFN_MAGIC ); lbp->b_ops = &xfs_dir3_leafn_buf_ops; +xfs_trans_buf_set_type (tp, lbp,XFS_BLF_DIR_LEAFN_BUF );xfs_dir3_leaf_log_header (tp, lbp);xfs_dir3_leaf_check (mp, lbp);return 0 ;
@@ -805,6 +814,7 @@ xfs_dir2_leafn_lookup_for_entry( (char *)curbp->b_addr); state->extrablk.magic =XFS_DIR2_DATA_MAGIC ; curbp->b_ops = &xfs_dir3_data_buf_ops; +xfs_trans_buf_set_type (tp, curbp,XFS_BLF_DIR_DATA_BUF );if (cmp ==XFS_CMP_EXACT )return XFS_ERROR (EEXIST ); }
@@ -819,6 +829,7 @@ xfs_dir2_leafn_lookup_for_entry( state->extrablk.blkno = curdb; state->extrablk.magic =XFS_DIR2_DATA_MAGIC ; curbp->b_ops = &xfs_dir3_data_buf_ops; +xfs_trans_buf_set_type (tp, curbp,XFS_BLF_DIR_DATA_BUF ); }else {/* If the curbp is not the CI match block, drop it */ if (state->extrablk.bp != curbp)
fs/xfs/xfs_dir2_priv.h +2 -0
@@ -49,6 +49,7 @@ extern int xfs_dir2_leaf_to_block(struct xfs_da_args *args,#endif extern const struct xfs_buf_ops xfs_dir3_data_buf_ops; +extern const struct xfs_buf_ops xfs_dir3_free_buf_ops;extern int __xfs_dir3_data_check (struct xfs_inode *dp,struct xfs_buf *bp); extern int xfs_dir3_data_read(struct xfs_trans *tp, struct xfs_inode *dp,
@@ -77,6 +78,7 @@ extern void xfs_dir2_data_use_free(struct xfs_trans *tp, struct xfs_buf *bp, xfs_dir2_data_aoff_t len, int *needlogp, int *needscanp);/* xfs_dir2_leaf.c */ +extern const struct xfs_buf_ops xfs_dir3_leaf1_buf_ops;extern const struct xfs_buf_ops xfs_dir3_leafn_buf_ops; extern int xfs_dir3_leafn_read(struct xfs_trans *tp, struct xfs_inode *dp,
fs/xfs/xfs_log_recover.c +180 -79
327 lines not on this page · raw message
fs/xfs/xfs_trans.h +2 -0
@@ -507,6 +507,8 @@ void xfs_trans_dquot_buf(xfs_trans_t *, struct xfs_buf *, uint);void xfs_trans_inode_alloc_buf (xfs_trans_t *,struct xfs_buf *);void xfs_trans_buf_set_type (struct xfs_trans *,struct xfs_buf *,uint ); +void xfs_trans_buf_copy_type (struct xfs_buf *dst_bp, +struct xfs_buf *src_bp);void xfs_trans_ichgtime (struct xfs_trans *,struct xfs_inode *,int );void xfs_trans_ijoin (struct xfs_trans *,struct xfs_inode *,uint );void xfs_trans_log_buf (xfs_trans_t *,struct xfs_buf *,uint ,uint );
fs/xfs/xfs_trans_buf.c +17 -0
@@ -768,6 +768,9 @@ xfs_trans_buf_set_type( {struct xfs_buf_log_item *bip = bp->b_fspriv; +if (!tp) +return ; +ASSERT (bp->b_transp == tp);ASSERT (bip !=NULL );ASSERT (atomic_read (&bip->bli_refcount) >0 );
@@ -777,6 +780,20 @@ xfs_trans_buf_set_type( bip->__bli_format.blf_flags |= type; } +void +xfs_trans_buf_copy_type ( +struct xfs_buf *dst_bp, +struct xfs_buf *src_bp) +{ +struct xfs_buf_log_item *sbip = src_bp->b_fspriv; +struct xfs_buf_log_item *dbip = dst_bp->b_fspriv; +uint type; + + type = sbip->__bli_format.blf_flags &XFS_BLF_TYPE_MASK ; + dbip->__bli_format.blf_flags &= ~XFS_BLF_TYPE_MASK ; + dbip->__bli_format.blf_flags |= type; +} +/* * Similar to xfs_trans_inode_buf(), this marks the buffer as a cluster of * dquots. However, unlike in inode buffer recovery, dquot buffers get
Signature · 6 lines
1.7.10.4 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
PATCH 21/21 xfs: add CRC checks to the superblock
In reply to Dave ChinnerFrom: Dave Chinner <[email protected]>
With the addition of CRCs, there is such a wide and varied change to the on disk format that it makes sense to bump the superblock version number rather than try to use feature bits for all the new functionality.
This commit introduces all the new superblock fields needed for all the new functionality: feature masks similar to ext4, separate project quota inodes, a LSN field for recovery and the CRC field.
This commit does not bump the superblock version number, however. That will be done as a separate commit at the end of the series after all the new functionality is present so we switch it all on in one commit. This means that we can slowly introduce the changes without them being active and hence maintain bisectability of the tree.
This patch is based on a patch originally written by myself back from SGI days, which was subsequently modified by Christoph Hellwig. There is relatively little of that patch remaining, but the history of the patch still should be acknowledged here.
--- fs/xfs/xfs_buf_item.h | 4 +- fs/xfs/xfs_log_recover.c | 8 ++++ fs/xfs/xfs_mount.c | 97 ++++++++++++++++++++++++++++++++++++-------- fs/xfs/xfs_mount.h | 1 + fs/xfs/xfs_sb.h | 100 ++++++++++++++++++++++++++++++++-------------- 5 files changed, 164 insertions(+), 46 deletions(-)
fs/xfs/xfs_buf_item.h +3 -1
@@ -58,6 +58,7 @@ extern kmem_zone_t *xfs_buf_item_zone;#define XFS_BLF_DA_NODE_BUF (1<<16)#define XFS_BLF_ATTR_LEAF_BUF (1<<17)#define XFS_BLF_ATTR_RMT_BUF (1<<18) +#define XFS_BLF_SB_BUF (1<<19)#define XFS_BLF_TYPE_MASK \ (XFS_BLF_UDQUOT_BUF | \
@@ -76,7 +77,8 @@ extern kmem_zone_t *xfs_buf_item_zone; XFS_BLF_DIR_LEAFN_BUF | \ XFS_BLF_DA_NODE_BUF | \ XFS_BLF_ATTR_LEAF_BUF | \ - XFS_BLF_ATTR_RMT_BUF) + XFS_BLF_ATTR_RMT_BUF | \ + XFS_BLF_SB_BUF)#define XFS_BLF_CHUNK 128#define XFS_BLF_SHIFT 7
fs/xfs/xfs_log_recover.c +8 -0
@@ -2040,6 +2040,14 @@ xlog_recovery_validate_buf_type( } bp->b_ops = &xfs_attr3_rmt_buf_ops;break ; +case XFS_BLF_SB_BUF : +if (magic32 !=XFS_SB_MAGIC ) { +xfs_warn (mp,"Bad SB block magic!" ); +ASSERT (0 ); +break ; + } + bp->b_ops = &xfs_sb_buf_ops; +break ;default :break ; }
fs/xfs/xfs_mount.c +81 -16
186 lines not on this page · raw message
fs/xfs/xfs_mount.h +1 -0
@@ -392,6 +392,7 @@ extern void xfs_set_low_space_thresholds(struct xfs_mount *);#endif /* __KERNEL__ */ +extern void xfs_sb_calc_crc (struct xfs_buf *);extern void xfs_mod_sb (struct xfs_trans *,__int64_t );extern int xfs_initialize_perag (struct xfs_mount *,xfs_agnumber_t ,xfs_agnumber_t *);
fs/xfs/xfs_sb.h +71 -29
229 lines not on this page · raw message
Signature · 6 lines
1.7.10.4 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 21/21] xfs: add CRC checks to the superblock
Quoted 31 lines · Dave Chinner
From: Dave Chinner <[email protected]>
With the addition of CRCs, there is such a wide and varied change to the on disk format that it makes sense to bump the superblock version number rather than try to use feature bits for all the new functionality.
This commit introduces all the new superblock fields needed for all the new functionality: feature masks similar to ext4, separate project quota inodes, a LSN field for recovery and the CRC field.
This commit does not bump the superblock version number, however. That will be done as a separate commit at the end of the series after all the new functionality is present so we switch it all on in one commit. This means that we can slowly introduce the changes without them being active and hence maintain bisectability of the tree.
This patch is based on a patch originally written by myself back from SGI days, which was subsequently modified by Christoph Hellwig. There is relatively little of that patch remaining, but the history of the patch still should be acknowledged here.
Signed-off-by Dave Chinner <[email protected]>--- fs/xfs/xfs_buf_item.h | 4 +- fs/xfs/xfs_log_recover.c | 8 ++++ fs/xfs/xfs_mount.c | 97 ++++++++++++++++++++++++++++++++++++-------- fs/xfs/xfs_mount.h | 1 + fs/xfs/xfs_sb.h | 100 ++++++++++++++++++++++++++++++++-------------- 5 files changed, 164 insertions(+), 46 deletions(-)
<snip>
Quoted 64 lines
fs/xfs/xfs_sb.h +29
-2@@ -32,6 +32,7 @@ struct xfs_mount;#define XFS_SB_VERSION_2 2/* 6.2 - attributes */ #define XFS_SB_VERSION_3 3/* 6.2 - new inode version */ #define XFS_SB_VERSION_4 4/* 6.2+ - bitmask version */ +#define XFS_SB_VERSION_5 5/* CRC enabled filesystem */ #define XFS_SB_VERSION_NUMBITS 0x000f#define XFS_SB_VERSION_ALLFBITS 0xfff0#define XFS_SB_VERSION_SASHFBITS 0xf000@@ -161,6 +162,18 @@ typedef struct xfs_sb {*/ __uint32_t sb_bad_features2; +/* version 5 superblock fields start here */ + +/* feature masks */ +__uint32_t sb_features_compat; +__uint32_t sb_features_ro_compat; +__uint32_t sb_features_incompat; + +__uint32_t sb_crc;/* superblock crc */ + +xfs_ino_t sb_pquotino;/* project quota inode */ +xfs_lsn_t sb_lsn;/* last write sequence */ +/* must be padded to 64 bit alignment */ } xfs_sb_t;@@ -229,7 +242,19 @@ typedef struct xfs_dsb {* for features2 bits. Easiest just to mark it bad and not use * it for anything else. */ -__be32 sb_bad_features2; +__be32 sb_bad_features2; + +/* version 5 superblock fields start here */ + +/* feature masks */ +__be32 sb_features_compat; +__be32 sb_features_ro_compat; +__be32 sb_features_incompat; + +__le32 sb_crc;/* superblock crc */ + +__be64 sb_pquotino;/* project quota inode */ +__be64 sb_lsn;/* last write sequence */ /* must be padded to 64 bit alignment */ } xfs_dsb_t;@@ -250,7 +275,9 @@ typedef enum {XFS_SBS_GQUOTINO ,XFS_SBS_QFLAGS ,XFS_SBS_FLAGS ,XFS_SBS_SHARED_VN ,XFS_SBS_INOALIGNMT ,XFS_SBS_UNIT ,XFS_SBS_WIDTH ,XFS_SBS_DIRBLKLOG ,XFS_SBS_LOGSECTLOG ,XFS_SBS_LOGSECTSIZE ,XFS_SBS_LOGSUNIT , -XFS_SBS_FEATURES2 ,XFS_SBS_BAD_FEATURES2 , +XFS_SBS_FEATURES2 ,XFS_SBS_BAD_FEATURES2 ,XFS_SBS_FEATURES_COMPAT , +XFS_SBS_FEATURES_RO_COMPAT ,XFS_SBS_FEATURES_INCOMPAT ,XFS_SBS_CRC , +XFS_SBS_PQUOTINO ,XFS_SBS_LSN , XFS_SBS_FIELDCOUNT } xfs_sb_field_t;
fs/xfs/xfs_sb.h typedef enum { · line 310
Quoted 8 lines
fs/xfs/xfs_sb.h +5
-0@@ -276,6 +303,11 @@ typedef enum {#define XFS_SB_FDBLOCKS XFS_SB_MVAL(FDBLOCKS)#define XFS_SB_FEATURES2 XFS_SB_MVAL(FEATURES2)#define XFS_SB_BAD_FEATURES2 XFS_SB_MVAL(BAD_FEATURES2) +#define XFS_SB_FEATURES_COMPAT XFS_SB_MVAL(FEATURES_COMPAT) +#define XFS_SB_FEATURES_RO_COMPAT XFS_SB_MVAL(FEATURES_RO_COMPAT) +#define XFS_SB_FEATURES_INCOMPAT XFS_SB_MVAL(FEATURES_INCOMPAT) +#define XFS_SB_CRC XFS_SB_MVAL(CRC) +#define XFS_SB_PQUOTINO XFS_SB_MVAL(PQUOTINO)
missing define for XFS_SB_LSN ?!
fs/xfs/xfs_sb.h typedef enum { · line 319
Quoted 10 lines
fs/xfs/xfs_sb.h +2
-1#define XFS_SB_NUM_BITS ((int)XFS_SBS_FIELDCOUNT)#define XFS_SB_ALL_BITS ((1LL << XFS_SB_NUM_BITS) - 1)#define XFS_SB_MOD_BITS \@@ -283,7 +315,8 @@ typedef enum {XFS_SB_VERSIONNUM |XFS_SB_UQUOTINO |XFS_SB_GQUOTINO | \XFS_SB_QFLAGS |XFS_SB_SHARED_VN |XFS_SB_UNIT |XFS_SB_WIDTH | \XFS_SB_ICOUNT |XFS_SB_IFREE |XFS_SB_FDBLOCKS |XFS_SB_FEATURES2 | \ - XFS_SB_BAD_FEATURES2) +XFS_SB_BAD_FEATURES2 |XFS_SB_FEATURES_COMPAT | \ + XFS_SB_FEATURES_RO_COMPAT | XFS_SB_FEATURES_INCOMPAT | XFS_SB_PQUOTINO)
missing XFS_SB_LSN ?!
Quoted 13 lines
fs/xfs/xfs_sb.h +2
-0/* @@ -325,6 +358,8 @@ static inline int xfs_sb_good_version(xfs_sb_t *sbp)return 1 ; } +if (XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_5 ) +return 1 ;return 0 ; }
fs/xfs/xfs_sb.h static inline int xfs_sb_version_hasattr(xfs_sb_t *sbp) · line 405
Quoted 7 lines
fs/xfs/xfs_sb.h +1
-1@@ -365,7 +400,7 @@ static inline int xfs_sb_version_hasattr(xfs_sb_t *sbp) {return sbp->sb_versionnum ==XFS_SB_VERSION_2 || sbp->sb_versionnum ==XFS_SB_VERSION_3 || - (XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_4 && + (XFS_SB_VERSION_NUM (sbp) >=XFS_SB_VERSION_4 && (sbp->sb_versionnum &XFS_SB_VERSION_ATTRBIT )); }
Do you expect version 5 and later have this bit to be exclusively set to use attribues ? (i.e can't we just assume version 5 and later would have attributes ?)
Since we are changing the version, can't we get rid of some on these bits (i.e slowly deprecate them) ?
Quoted 11 lines
fs/xfs/xfs_sb.h +1
-1@@ -373,7 +408,7 @@ static inline void xfs_sb_version_addattr(xfs_sb_t *sbp) {if (sbp->sb_versionnum ==XFS_SB_VERSION_1 ) sbp->sb_versionnum =XFS_SB_VERSION_2 ; -else if (XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_4 ) +else if (XFS_SB_VERSION_NUM (sbp) >=XFS_SB_VERSION_4 ) sbp->sb_versionnum |=XFS_SB_VERSION_ATTRBIT ;else sbp->sb_versionnum =XFS_SB_VERSION_4 |XFS_SB_VERSION_ATTRBIT ;
fs/xfs/xfs_sb.h static inline void xfs_sb_version_addattr(xfs_sb_t *sbp) · line 421
Quoted 6 lines
fs/xfs/xfs_sb.h +1
-1@@ -382,7 +417,7 @@ static inline void xfs_sb_version_addattr(xfs_sb_t *sbp)static inline int xfs_sb_version_hasnlink (xfs_sb_t *sbp) {return sbp->sb_versionnum ==XFS_SB_VERSION_3 || - (XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_4 && + (XFS_SB_VERSION_NUM (sbp) >=XFS_SB_VERSION_4 && (sbp->sb_versionnum &XFS_SB_VERSION_NLINKBIT ));
Same here
fs/xfs/xfs_sb.h static inline void xfs_sb_version_addnlink(xfs_sb_t *sbp) · line 435
Quoted 9 lines
fs/xfs/xfs_sb.h +1
-1}@@ -396,13 +431,13 @@ static inline void xfs_sb_version_addnlink(xfs_sb_t *sbp)static inline int xfs_sb_version_hasquota (xfs_sb_t *sbp) { -return XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_4 && +return XFS_SB_VERSION_NUM (sbp) >=XFS_SB_VERSION_4 && (sbp->sb_versionnum &XFS_SB_VERSION_QUOTABIT );
same here
Quoted 10 lines
fs/xfs/xfs_sb.h +1
-1}static inline void xfs_sb_version_addquota (xfs_sb_t *sbp) { -if (XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_4 ) +if (XFS_SB_VERSION_NUM (sbp) >=XFS_SB_VERSION_4 ) sbp->sb_versionnum |=XFS_SB_VERSION_QUOTABIT ;else sbp->sb_versionnum = xfs_sb_version_tonew(sbp->sb_versionnum) |
fs/xfs/xfs_sb.h static inline void xfs_sb_version_addquota(xfs_sb_t *sbp) · line 452
Quoted 9 lines
fs/xfs/xfs_sb.h +3
-2@@ -411,13 +446,14 @@ static inline void xfs_sb_version_addquota(xfs_sb_t *sbp)static inline int xfs_sb_version_hasalign (xfs_sb_t *sbp) { -return XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_4 && - (sbp->sb_versionnum &XFS_SB_VERSION_ALIGNBIT ); +return (XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_5 ) || + (XFS_SB_VERSION_NUM (sbp) >=XFS_SB_VERSION_4 && + (sbp->sb_versionnum &XFS_SB_VERSION_ALIGNBIT )); }
same here
fs/xfs/xfs_sb.h static inline void xfs_sb_version_addquota(xfs_sb_t *sbp) · line 458
Quoted 7 lines
fs/xfs/xfs_sb.h +1
-1static inline int xfs_sb_version_hasdalign (xfs_sb_t *sbp) { -return XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_4 && +return XFS_SB_VERSION_NUM (sbp) >=XFS_SB_VERSION_4 && (sbp->sb_versionnum &XFS_SB_VERSION_DALIGNBIT ); }
same here
fs/xfs/xfs_sb.h static inline int xfs_sb_version_hasshared(xfs_sb_t *sbp) · line 468
Quoted 8 lines
fs/xfs/xfs_sb.h +1
-2@@ -429,38 +465,42 @@ static inline int xfs_sb_version_hasshared(xfs_sb_t *sbp)static inline int xfs_sb_version_hasdirv2 (xfs_sb_t *sbp) { -return XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_4 && - (sbp->sb_versionnum &XFS_SB_VERSION_DIRV2BIT ); + return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) ||
Why some places we have version == 5 and others (version == 5 && (XXX))
Quoted 25 lines
fs/xfs/xfs_sb.h +8
-5+ (XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_4 && + (sbp->sb_versionnum &XFS_SB_VERSION_DIRV2BIT )); }static inline int xfs_sb_version_haslogv2 (xfs_sb_t *sbp) { -return XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_4 && - (sbp->sb_versionnum &XFS_SB_VERSION_LOGV2BIT ); +return (XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_5 ) || + (XFS_SB_VERSION_NUM (sbp) >=XFS_SB_VERSION_4 && + (sbp->sb_versionnum &XFS_SB_VERSION_LOGV2BIT )); }static inline int xfs_sb_version_hasextflgbit (xfs_sb_t *sbp) { -return XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_4 && - (sbp->sb_versionnum &XFS_SB_VERSION_EXTFLGBIT ); +return (XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_5 ) || + (XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_4 && + (sbp->sb_versionnum &XFS_SB_VERSION_EXTFLGBIT )); }static inline int xfs_sb_version_hassector (xfs_sb_t *sbp) { - return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4 &&
fs/xfs/xfs_sb.h static inline int xfs_sb_version_hasshared(xfs_sb_t *sbp) · line 497
Quoted 10 lines
fs/xfs/xfs_sb.h +2
-1+return XFS_SB_VERSION_NUM (sbp) >=XFS_SB_VERSION_4 && (sbp->sb_versionnum &XFS_SB_VERSION_SECTORBIT ); }static inline int xfs_sb_version_hasasciici (xfs_sb_t *sbp) { -return XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_4 && +return XFS_SB_VERSION_NUM (sbp) >=XFS_SB_VERSION_4 && (sbp->sb_versionnum &XFS_SB_VERSION_BORGBIT ); }
same here ?!
fs/xfs/xfs_sb.h static inline int xfs_sb_version_hasshared(xfs_sb_t *sbp) · line 503
Quoted 8 lines
fs/xfs/xfs_sb.h +3
-2static inline int xfs_sb_version_hasmorebits (xfs_sb_t *sbp) { -return XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_4 && - (sbp->sb_versionnum &XFS_SB_VERSION_MOREBITSBIT ); +return (XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_5 ) || + (XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_4 && + (sbp->sb_versionnum &XFS_SB_VERSION_MOREBITSBIT ));
Gets more confusing here. version 5 means it has more bits ? (even if the MOREBITSBIT is not set ?
May be we shouldn't add version 5 check here ?!
fs/xfs/xfs_sb.h static inline int xfs_sb_version_hasmorebits(xfs_sb_t *sbp) · line 521
Quoted 13 lines
fs/xfs/xfs_sb.h +3
-2}/* @@ -475,14 +515,16 @@ static inline int xfs_sb_version_hasmorebits(xfs_sb_t *sbp)static inline int xfs_sb_version_haslazysbcount (xfs_sb_t *sbp) { -return xfs_sb_version_hasmorebits (sbp) && - (sbp->sb_features2 &XFS_SB_VERSION2_LAZYSBCOUNTBIT ); +return (XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_5 ) || + (xfs_sb_version_hasmorebits (sbp) && + (sbp->sb_features2 &XFS_SB_VERSION2_LAZYSBCOUNTBIT )); }
If we remove the version 5 check in xfs_sb_hasmorebits(), then this change is correct. Otherwise, this change is not needed.
fs/xfs/xfs_sb.h static inline int xfs_sb_version_hasmorebits(xfs_sb_t *sbp) · line 528
Quoted 9 lines
fs/xfs/xfs_sb.h +3
-2static inline int xfs_sb_version_hasattr2 (xfs_sb_t *sbp) { -return xfs_sb_version_hasmorebits (sbp) && - (sbp->sb_features2 &XFS_SB_VERSION2_ATTR2BIT ); +return (XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_5 ) || + (xfs_sb_version_hasmorebits (sbp) && + (sbp->sb_features2 &XFS_SB_VERSION2_ATTR2BIT )); }
If we remove the version 5 check in xfs_sb_hasmorebits(), then this change is correct. Otherwise, this change is not needed.
fs/xfs/xfs_sb.h static inline void xfs_sb_version_removeattr2(xfs_sb_t *sbp) · line 548
Quoted 12 lines
fs/xfs/xfs_sb.h +3
-2static inline void xfs_sb_version_addattr2 (xfs_sb_t *sbp)@@ -500,14 +542,14 @@ static inline void xfs_sb_version_removeattr2(xfs_sb_t *sbp)static inline int xfs_sb_version_hasprojid32bit (xfs_sb_t *sbp) { -return xfs_sb_version_hasmorebits (sbp) && - (sbp->sb_features2 &XFS_SB_VERSION2_PROJID32BIT ); +return (XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_5 ) || + (xfs_sb_version_hasmorebits (sbp) && + (sbp->sb_features2 &XFS_SB_VERSION2_PROJID32BIT )); }
If we remove the version 5 check in xfs_sb_hasmorebits(), then this change is correct. Otherwise, this change is not needed.
fs/xfs/xfs_sb.h static inline void xfs_sb_version_removeattr2(xfs_sb_t *sbp) · line 552
Quoted 6 lines
fs/xfs/xfs_sb.h +1
-2static inline int xfs_sb_version_hascrc (xfs_sb_t *sbp) { -return (xfs_sb_version_hasmorebits (sbp) && - (sbp->sb_features2 &XFS_SB_VERSION2_CRCBIT )); +return XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_5 ;
what happens to the superblocks that already have version 4 and this bit set ?
Also don't xfs_sb_version_toold() and xfs_sb_version_tonew() need changes ?
I see that xfs_sb_version_toold() is not used anywhere, can we remove it ?
fs/xfs/xfs_sb.h static inline void xfs_sb_version_removeattr2(xfs_sb_t *sbp) · line 554
Quoted 3 lines
fs/xfs/xfs_sb.h +0
-0}/*
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 21/21] xfs: add CRC checks to the superblock
Quoted 34 lines · Chandra Seetharaman
Quoted 31 lines · Dave Chinner
From: Dave Chinner <[email protected]>
With the addition of CRCs, there is such a wide and varied change to the on disk format that it makes sense to bump the superblock version number rather than try to use feature bits for all the new functionality.
This commit introduces all the new superblock fields needed for all the new functionality: feature masks similar to ext4, separate project quota inodes, a LSN field for recovery and the CRC field.
This commit does not bump the superblock version number, however. That will be done as a separate commit at the end of the series after all the new functionality is present so we switch it all on in one commit. This means that we can slowly introduce the changes without them being active and hence maintain bisectability of the tree.
This patch is based on a patch originally written by myself back from SGI days, which was subsequently modified by Christoph Hellwig. There is relatively little of that patch remaining, but the history of the patch still should be acknowledged here.
Signed-off-by Dave Chinner <[email protected]>--- fs/xfs/xfs_buf_item.h | 4 +- fs/xfs/xfs_log_recover.c | 8 ++++ fs/xfs/xfs_mount.c | 97 ++++++++++++++++++++++++++++++++++++-------- fs/xfs/xfs_mount.h | 1 + fs/xfs/xfs_sb.h | 100 ++++++++++++++++++++++++++++++++-------------- 5 files changed, 164 insertions(+), 46 deletions(-)<snip>
.....
Quoted 11 lines
fs/xfs/xfs_sb.h typedef enum { · line 310
Quoted 9 lines
fs/xfs/xfs_sb.h +5
-0@@ -276,6 +303,11 @@ typedef enum {#define XFS_SB_FDBLOCKS XFS_SB_MVAL(FDBLOCKS)#define XFS_SB_FEATURES2 XFS_SB_MVAL(FEATURES2)#define XFS_SB_BAD_FEATURES2 XFS_SB_MVAL(BAD_FEATURES2) +#define XFS_SB_FEATURES_COMPAT XFS_SB_MVAL(FEATURES_COMPAT) +#define XFS_SB_FEATURES_RO_COMPAT XFS_SB_MVAL(FEATURES_RO_COMPAT) +#define XFS_SB_FEATURES_INCOMPAT XFS_SB_MVAL(FEATURES_INCOMPAT) +#define XFS_SB_CRC XFS_SB_MVAL(CRC) +#define XFS_SB_PQUOTINO XFS_SB_MVAL(PQUOTINO)missing define for
XFS_SB_LSN?!
No, not at all. We only have bits for variables that get logged. The LSn of the object is never logged as it is stamped into the object when it is being written back. i.e. it is an indication of when the object was last modified, not a field that is recorded during modifications.
Quoted 7 lines
Quoted 7 lines
fs/xfs/xfs_sb.h +2
-0@@ -325,6 +358,8 @@ static inline int xfs_sb_good_version(xfs_sb_t *sbp)return 1 ; } +if (XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_5 ) +return 1 ;
Quoted 14 lines
fs/xfs/xfs_sb.h static inline int xfs_sb_version_hasattr(xfs_sb_t *sbp) · line 405
Quoted 10 lines
fs/xfs/xfs_sb.h +1
-1return 0 ; }@@ -365,7 +400,7 @@ static inline int xfs_sb_version_hasattr(xfs_sb_t *sbp) {return sbp->sb_versionnum ==XFS_SB_VERSION_2 || sbp->sb_versionnum ==XFS_SB_VERSION_3 || - (XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_4 && + (XFS_SB_VERSION_NUM (sbp) >=XFS_SB_VERSION_4 && (sbp->sb_versionnum &XFS_SB_VERSION_ATTRBIT )); }Do you expect version 5 and later have this bit to be exclusively set to use attribues ? (i.e can't we just assume version 5 and later would have attributes ?)
This just indicates that there are inodes with attributes in the filesystem. It's not an "enabling" feature at all. If it's not present when the first attribute is created, then the kernel code will set it. Hence all this does it maintain the existing behaviour....
Quoted 2 lines
Since we are changing the version, can't we get rid of some on these bits (i.e slowly deprecate them) ?
No, because we still support version 4 superblocks and hence all these bit for the indefinite future (i.e. forever).
Quoted 10 lines
Quoted 10 lines
fs/xfs/xfs_sb.h +1
-1@@ -373,7 +408,7 @@ static inline void xfs_sb_version_addattr(xfs_sb_t *sbp) {if (sbp->sb_versionnum ==XFS_SB_VERSION_1 ) sbp->sb_versionnum =XFS_SB_VERSION_2 ; -else if (XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_4 ) +else if (XFS_SB_VERSION_NUM (sbp) >=XFS_SB_VERSION_4 ) sbp->sb_versionnum |=XFS_SB_VERSION_ATTRBIT ;else sbp->sb_versionnum =XFS_SB_VERSION_4 |XFS_SB_VERSION_ATTRBIT ;@@ -382,7 +417,7 @@ static inline void xfs_sb_version_addattr(xfs_sb_t *sbp)
Quoted 8 lines
fs/xfs/xfs_sb.h static inline void xfs_sb_version_addattr(xfs_sb_t *sbp) · line 421
Quoted 6 lines
fs/xfs/xfs_sb.h +1
-1static inline int xfs_sb_version_hasnlink (xfs_sb_t *sbp) {return sbp->sb_versionnum ==XFS_SB_VERSION_3 || - (XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_4 && + (XFS_SB_VERSION_NUM (sbp) >=XFS_SB_VERSION_4 && (sbp->sb_versionnum &XFS_SB_VERSION_NLINKBIT ));Same here
This is for version 1/2 inodes and which formats are present in the filesystem. It has been set by default in mkfs for a long time. Version 5 superblocks don't change this. This bit can also be set on demand by the kernel if it is not present and an inode requires a link count of > 2^16.
Further, CRCs require v3 inodes, so this is only relevant for non-crc enabled filesystems.
Quoted 9 lines
fs/xfs/xfs_sb.h static inline void xfs_sb_version_addnlink(xfs_sb_t *sbp) · line 435
Quoted 7 lines
fs/xfs/xfs_sb.h +1
-1@@ -396,13 +431,13 @@ static inline void xfs_sb_version_addnlink(xfs_sb_t *sbp)static inline int xfs_sb_version_hasquota (xfs_sb_t *sbp) { -return XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_4 && +return XFS_SB_VERSION_NUM (sbp) >=XFS_SB_VERSION_4 && (sbp->sb_versionnum &XFS_SB_VERSION_QUOTABIT );same here
Set when quotas are turned on by the kernel. Behaves the same for v4/v5 superblocks.
Quoted 11 lines
Quoted 11 lines
fs/xfs/xfs_sb.h +1
-1}static inline void xfs_sb_version_addquota (xfs_sb_t *sbp) { -if (XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_4 ) +if (XFS_SB_VERSION_NUM (sbp) >=XFS_SB_VERSION_4 ) sbp->sb_versionnum |=XFS_SB_VERSION_QUOTABIT ;else sbp->sb_versionnum = xfs_sb_version_tonew(sbp->sb_versionnum) |@@ -411,13 +446,14 @@ static inline void xfs_sb_version_addquota(xfs_sb_t *sbp)
Quoted 10 lines
fs/xfs/xfs_sb.h static inline void xfs_sb_version_addquota(xfs_sb_t *sbp) · line 452
Quoted 8 lines
fs/xfs/xfs_sb.h +3
-2static inline int xfs_sb_version_hasalign (xfs_sb_t *sbp) { -return XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_4 && - (sbp->sb_versionnum &XFS_SB_VERSION_ALIGNBIT ); +return (XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_5 ) || + (XFS_SB_VERSION_NUM (sbp) >=XFS_SB_VERSION_4 && + (sbp->sb_versionnum &XFS_SB_VERSION_ALIGNBIT )); }same here
mkfs already sets this bit unconditionally for v4 superblocks, so V5 makes it mandatory.
Quoted 8 lines
fs/xfs/xfs_sb.h static inline void xfs_sb_version_addquota(xfs_sb_t *sbp) · line 458
Quoted 6 lines
fs/xfs/xfs_sb.h +1
-1static inline int xfs_sb_version_hasdalign (xfs_sb_t *sbp) { -return XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_4 && +return XFS_SB_VERSION_NUM (sbp) >=XFS_SB_VERSION_4 && (sbp->sb_versionnum &XFS_SB_VERSION_DALIGNBIT ); }same here
Necessary to indicate sunit/swidth are set at mkfs time, indicating alignment restrictions are present on filesystem layout. Behaves the same for v4/v5 superblocks.
Quoted 9 lines
fs/xfs/xfs_sb.h static inline int xfs_sb_version_hasshared(xfs_sb_t *sbp) · line 468
Quoted 7 lines
fs/xfs/xfs_sb.h +1
-2@@ -429,38 +465,42 @@ static inline int xfs_sb_version_hasshared(xfs_sb_t *sbp)static inline int xfs_sb_version_hasdirv2 (xfs_sb_t *sbp) { -return XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_4 && - (sbp->sb_versionnum &XFS_SB_VERSION_DIRV2BIT ); + return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) ||Why some places we have version == 5 and others (version == 5 && (XXX))
Because some things are simply set as supported on v5 superblocks, while other are still optional or indicative of on-disk formats in use.
Quoted 11 lines
fs/xfs/xfs_sb.h static inline int xfs_sb_version_hasshared(xfs_sb_t *sbp) · line 503
Quoted 7 lines
fs/xfs/xfs_sb.h +3
-2static inline int xfs_sb_version_hasmorebits (xfs_sb_t *sbp) { -return XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_4 && - (sbp->sb_versionnum &XFS_SB_VERSION_MOREBITSBIT ); +return (XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_5 ) || + (XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_4 && + (sbp->sb_versionnum &XFS_SB_VERSION_MOREBITSBIT ));Gets more confusing here. version 5 means it has more bits ? (even if the MOREBITSBIT is not set ?
Quoted 1 line
May be we shouldn't add version 5 check here ?!
The MOREBITSBIT bit means that the sb_features2 field exists in the on disk structure. That is clearly true for all v5 superblocks, and so we don't need to care if the MOREBITSBIT is set or not.
Quoted 13 lines
fs/xfs/xfs_sb.h static inline int xfs_sb_version_hasmorebits(xfs_sb_t *sbp) · line 521
Quoted 10 lines
fs/xfs/xfs_sb.h +3
-2@@ -475,14 +515,16 @@ static inline int xfs_sb_version_hasmorebits(xfs_sb_t *sbp)static inline int xfs_sb_version_haslazysbcount (xfs_sb_t *sbp) { -return xfs_sb_version_hasmorebits (sbp) && - (sbp->sb_features2 &XFS_SB_VERSION2_LAZYSBCOUNTBIT ); +return (XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_5 ) || + (xfs_sb_version_hasmorebits (sbp) && + (sbp->sb_features2 &XFS_SB_VERSION2_LAZYSBCOUNTBIT )); }If we remove the version 5 check in
xfs_sb_hasmorebits(), then this change is correct. Otherwise, this change is not needed.
No, this change means lazy superblock counters are a fixed feature of v5 superblocks - it is not optional like it currently is. The check inside xfs_sb_version_hasmorebits() is to determine if the features2 field is present, not that the lazycount feature is supported....
Quoted 11 lines
fs/xfs/xfs_sb.h static inline int xfs_sb_version_hasmorebits(xfs_sb_t *sbp) · line 528
Quoted 8 lines
fs/xfs/xfs_sb.h +3
-2static inline int xfs_sb_version_hasattr2 (xfs_sb_t *sbp) { -return xfs_sb_version_hasmorebits (sbp) && - (sbp->sb_features2 &XFS_SB_VERSION2_ATTR2BIT ); +return (XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_5 ) || + (xfs_sb_version_hasmorebits (sbp) && + (sbp->sb_features2 &XFS_SB_VERSION2_ATTR2BIT )); }If we remove the version 5 check in
xfs_sb_hasmorebits(), then this change is correct. Otherwise, this change is not needed.
Same again - v5 implies attr2 behaviour is the only attr fork behaviour supported.
Quoted 13 lines
fs/xfs/xfs_sb.h static inline void xfs_sb_version_removeattr2(xfs_sb_t *sbp) · line 548
Quoted 11 lines
fs/xfs/xfs_sb.h +3
-2static inline void xfs_sb_version_addattr2 (xfs_sb_t *sbp)@@ -500,14 +542,14 @@ static inline void xfs_sb_version_removeattr2(xfs_sb_t *sbp)static inline int xfs_sb_version_hasprojid32bit (xfs_sb_t *sbp) { -return xfs_sb_version_hasmorebits (sbp) && - (sbp->sb_features2 &XFS_SB_VERSION2_PROJID32BIT ); +return (XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_5 ) || + (xfs_sb_version_hasmorebits (sbp) && + (sbp->sb_features2 &XFS_SB_VERSION2_PROJID32BIT )); }If we remove the version 5 check in
xfs_sb_hasmorebits(), then this change is correct. Otherwise, this change is not needed.
Same again - v5 superblocks *always* support 32 bit project ids.
Quoted 8 lines
fs/xfs/xfs_sb.h static inline void xfs_sb_version_removeattr2(xfs_sb_t *sbp) · line 552
Quoted 5 lines
fs/xfs/xfs_sb.h +1
-2static inline int xfs_sb_version_hascrc (xfs_sb_t *sbp) { -return (xfs_sb_version_hasmorebits (sbp) && - (sbp->sb_features2 &XFS_SB_VERSION2_CRCBIT )); +return XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_5 ;what happens to the superblocks that already have version 4 and this bit set ?
It makes the XFS_SB_VERSION2_CRCBIT an invalid feature bit - it has never, ever been used by anything - so any filesystem with that bit set will fail to mount.
Quoted 2 lines
Also don't
xfs_sb_version_toold()andxfs_sb_version_tonew()need changes ?
No. the code that calls xfs_sb_version_tonew() only does so for superblocks whose version is <= 3. i.e. filesystems that came from Irix 6.2 or earlier....
Quoted 2 lines
I see that
xfs_sb_version_toold()is not used anywhere, can we remove it ?
Used by userspace, and seeing as this file is common between kernel and userspace, it hasn't been removed as that simply imposes higher maintenance cost on us.
Cheers,
Dave.
Signature · 7 lines
Dave Chinner [email protected] _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 21/21] xfs: add CRC checks to the superblock
Hi Dave,
Thanks for patiently explaining the details.
Please see my comments below.
Quoted 48 lines · Dave Chinner
Quoted 34 lines · Chandra Seetharaman
Quoted 31 lines · Dave Chinner
From: Dave Chinner <[email protected]>
With the addition of CRCs, there is such a wide and varied change to the on disk format that it makes sense to bump the superblock version number rather than try to use feature bits for all the new functionality.
This commit introduces all the new superblock fields needed for all the new functionality: feature masks similar to ext4, separate project quota inodes, a LSN field for recovery and the CRC field.
This commit does not bump the superblock version number, however. That will be done as a separate commit at the end of the series after all the new functionality is present so we switch it all on in one commit. This means that we can slowly introduce the changes without them being active and hence maintain bisectability of the tree.
This patch is based on a patch originally written by myself back from SGI days, which was subsequently modified by Christoph Hellwig. There is relatively little of that patch remaining, but the history of the patch still should be acknowledged here.
Signed-off-by Dave Chinner <[email protected]>--- fs/xfs/xfs_buf_item.h | 4 +- fs/xfs/xfs_log_recover.c | 8 ++++ fs/xfs/xfs_mount.c | 97 ++++++++++++++++++++++++++++++++++++-------- fs/xfs/xfs_mount.h | 1 + fs/xfs/xfs_sb.h | 100 ++++++++++++++++++++++++++++++++-------------- 5 files changed, 164 insertions(+), 46 deletions(-)<snip>
.....
Quoted 11 lines
fs/xfs/xfs_sb.h typedef enum { · line 310
Quoted 9 lines
fs/xfs/xfs_sb.h +5
-0@@ -276,6 +303,11 @@ typedef enum {#define XFS_SB_FDBLOCKS XFS_SB_MVAL(FDBLOCKS)#define XFS_SB_FEATURES2 XFS_SB_MVAL(FEATURES2)#define XFS_SB_BAD_FEATURES2 XFS_SB_MVAL(BAD_FEATURES2) +#define XFS_SB_FEATURES_COMPAT XFS_SB_MVAL(FEATURES_COMPAT) +#define XFS_SB_FEATURES_RO_COMPAT XFS_SB_MVAL(FEATURES_RO_COMPAT) +#define XFS_SB_FEATURES_INCOMPAT XFS_SB_MVAL(FEATURES_INCOMPAT) +#define XFS_SB_CRC XFS_SB_MVAL(CRC) +#define XFS_SB_PQUOTINO XFS_SB_MVAL(PQUOTINO)missing define for
XFS_SB_LSN?!
Quoted 5 lines
No, not at all. We only have bits for variables that get logged. The LSn of the object is never logged as it is stamped into the object when it is being written back. i.e. it is an indication of when the object was last modified, not a field that is recorded during modifications.
Hmm. may be I misunderstood. Aren't these bits to inform the low level function (that selects which fields in superblocks are updated) which fields we want to update on the disk ?
Quoted 29 lines
Quoted 8 lines
Quoted 8 lines
fs/xfs/xfs_sb.h +2
-0@@ -325,6 +358,8 @@ static inline int xfs_sb_good_version(xfs_sb_t *sbp)return 1 ; } +if (XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_5 ) +return 1 ;Quoted 14 lines
fs/xfs/xfs_sb.h static inline int xfs_sb_version_hasattr(xfs_sb_t *sbp) · line 405
Quoted 10 lines
fs/xfs/xfs_sb.h +1
-1return 0 ; }@@ -365,7 +400,7 @@ static inline int xfs_sb_version_hasattr(xfs_sb_t *sbp) {return sbp->sb_versionnum ==XFS_SB_VERSION_2 || sbp->sb_versionnum ==XFS_SB_VERSION_3 || - (XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_4 && + (XFS_SB_VERSION_NUM (sbp) >=XFS_SB_VERSION_4 && (sbp->sb_versionnum &XFS_SB_VERSION_ATTRBIT )); }Do you expect version 5 and later have this bit to be exclusively set to use attribues ? (i.e can't we just assume version 5 and later would have attributes ?)
This just indicates that there are inodes with attributes in the filesystem. It's not an "enabling" feature at all. If it's not present when the first attribute is created, then the kernel code will set it. Hence all this does it maintain the existing behaviour....
Quoted 5 lines
Quoted 2 lines
Since we are changing the version, can't we get rid of some on these bits (i.e slowly deprecate them) ?
No, because we still support version 4 superblocks and hence all these bit for the indefinite future (i.e. forever).
Sorry. I used a wrong word "deprecate". That is not what I meant.
I wanted to see if by deliberately making few of the bits in versionnum/features2 implicit in version 5 can we start using the _same_ bits in version 5 for new features. Mainly to avoid added features3, feature4... fields in the future. (my questions came from that point of view).
Basically, assume if version 4 has features bit A B C D E F, and version 5 implicitly means A D E F are set (i.e we do not have to use those bits in version 5 for those specific features), and B and C are optional which could still be used in version 5.
Quoted 1 line
From your explanation, it is clear that some features are implicit in
version 5 (and hence setting the bit is not needed). ATTRBIT, NLINKBIT, and QUOTABIT seems to be optional (and still could be used in version 5), and all others are implicit.
Even though some of the features are now implicit, and the corresponding bits are not used, i see that the plan is to keep the bits as is (without reusing). Is that correct ?
Do you see any value in reusing the bits ?
Quoted 90 lines
Quoted 11 lines
Quoted 11 lines
fs/xfs/xfs_sb.h +1
-1@@ -373,7 +408,7 @@ static inline void xfs_sb_version_addattr(xfs_sb_t *sbp) {if (sbp->sb_versionnum ==XFS_SB_VERSION_1 ) sbp->sb_versionnum =XFS_SB_VERSION_2 ; -else if (XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_4 ) +else if (XFS_SB_VERSION_NUM (sbp) >=XFS_SB_VERSION_4 ) sbp->sb_versionnum |=XFS_SB_VERSION_ATTRBIT ;else sbp->sb_versionnum =XFS_SB_VERSION_4 |XFS_SB_VERSION_ATTRBIT ;@@ -382,7 +417,7 @@ static inline void xfs_sb_version_addattr(xfs_sb_t *sbp)Quoted 8 lines
fs/xfs/xfs_sb.h static inline void xfs_sb_version_addattr(xfs_sb_t *sbp) · line 421
Quoted 6 lines
fs/xfs/xfs_sb.h +1
-1static inline int xfs_sb_version_hasnlink (xfs_sb_t *sbp) {return sbp->sb_versionnum ==XFS_SB_VERSION_3 || - (XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_4 && + (XFS_SB_VERSION_NUM (sbp) >=XFS_SB_VERSION_4 && (sbp->sb_versionnum &XFS_SB_VERSION_NLINKBIT ));Same here
This is for version 1/2 inodes and which formats are present in the filesystem. It has been set by default in mkfs for a long time. Version 5 superblocks don't change this. This bit can also be set on demand by the kernel if it is not present and an inode requires a link count of > 2^16.
Further, CRCs require v3 inodes, so this is only relevant for non-crc enabled filesystems.
Quoted 9 lines
fs/xfs/xfs_sb.h static inline void xfs_sb_version_addnlink(xfs_sb_t *sbp) · line 435
Quoted 7 lines
fs/xfs/xfs_sb.h +1
-1@@ -396,13 +431,13 @@ static inline void xfs_sb_version_addnlink(xfs_sb_t *sbp)static inline int xfs_sb_version_hasquota (xfs_sb_t *sbp) { -return XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_4 && +return XFS_SB_VERSION_NUM (sbp) >=XFS_SB_VERSION_4 && (sbp->sb_versionnum &XFS_SB_VERSION_QUOTABIT );same here
Set when quotas are turned on by the kernel. Behaves the same for v4/v5 superblocks.
Quoted 11 lines
Quoted 11 lines
fs/xfs/xfs_sb.h +1
-1}static inline void xfs_sb_version_addquota (xfs_sb_t *sbp) { -if (XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_4 ) +if (XFS_SB_VERSION_NUM (sbp) >=XFS_SB_VERSION_4 ) sbp->sb_versionnum |=XFS_SB_VERSION_QUOTABIT ;else sbp->sb_versionnum = xfs_sb_version_tonew(sbp->sb_versionnum) |@@ -411,13 +446,14 @@ static inline void xfs_sb_version_addquota(xfs_sb_t *sbp)Quoted 10 lines
fs/xfs/xfs_sb.h static inline void xfs_sb_version_addquota(xfs_sb_t *sbp) · line 452
Quoted 8 lines
fs/xfs/xfs_sb.h +3
-2static inline int xfs_sb_version_hasalign (xfs_sb_t *sbp) { -return XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_4 && - (sbp->sb_versionnum &XFS_SB_VERSION_ALIGNBIT ); +return (XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_5 ) || + (XFS_SB_VERSION_NUM (sbp) >=XFS_SB_VERSION_4 && + (sbp->sb_versionnum &XFS_SB_VERSION_ALIGNBIT )); }same here
mkfs already sets this bit unconditionally for v4 superblocks, so V5 makes it mandatory.
Quoted 8 lines
fs/xfs/xfs_sb.h static inline void xfs_sb_version_addquota(xfs_sb_t *sbp) · line 458
Quoted 6 lines
fs/xfs/xfs_sb.h +1
-1static inline int xfs_sb_version_hasdalign (xfs_sb_t *sbp) { -return XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_4 && +return XFS_SB_VERSION_NUM (sbp) >=XFS_SB_VERSION_4 && (sbp->sb_versionnum &XFS_SB_VERSION_DALIGNBIT ); }same here
Necessary to indicate sunit/swidth are set at mkfs time, indicating alignment restrictions are present on filesystem layout. Behaves the same for v4/v5 superblocks.
Quoted 9 lines
fs/xfs/xfs_sb.h static inline int xfs_sb_version_hasshared(xfs_sb_t *sbp) · line 468
Quoted 7 lines
fs/xfs/xfs_sb.h +1
-2@@ -429,38 +465,42 @@ static inline int xfs_sb_version_hasshared(xfs_sb_t *sbp)static inline int xfs_sb_version_hasdirv2 (xfs_sb_t *sbp) { -return XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_4 && - (sbp->sb_versionnum &XFS_SB_VERSION_DIRV2BIT ); + return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) ||Why some places we have version == 5 and others (version == 5 && (XXX))
Quoted 3 lines
Because some things are simply set as supported on v5 superblocks, while other are still optional or indicative of on-disk formats in use.
Clear now.
Quoted 12 lines
Quoted 12 lines
fs/xfs/xfs_sb.h static inline int xfs_sb_version_hasshared(xfs_sb_t *sbp) · line 503
Quoted 8 lines
fs/xfs/xfs_sb.h +3
-2static inline int xfs_sb_version_hasmorebits (xfs_sb_t *sbp) { -return XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_4 && - (sbp->sb_versionnum &XFS_SB_VERSION_MOREBITSBIT ); +return (XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_5 ) || + (XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_4 && + (sbp->sb_versionnum &XFS_SB_VERSION_MOREBITSBIT ));Gets more confusing here. version 5 means it has more bits ? (even if the MOREBITSBIT is not set ?
Quoted 5 lines
Quoted 1 line
May be we shouldn't add version 5 check here ?!
The MOREBITSBIT bit means that the
sb_features2field exists in the on disk structure. That is clearly true for all v5 superblocks, and so we don't need to care if the MOREBITSBIT is set or not.
Understood.
Quoted 75 lines
Quoted 14 lines
fs/xfs/xfs_sb.h static inline int xfs_sb_version_hasmorebits(xfs_sb_t *sbp) · line 521
Quoted 11 lines
fs/xfs/xfs_sb.h +3
-2@@ -475,14 +515,16 @@ static inline int xfs_sb_version_hasmorebits(xfs_sb_t *sbp)static inline int xfs_sb_version_haslazysbcount (xfs_sb_t *sbp) { -return xfs_sb_version_hasmorebits (sbp) && - (sbp->sb_features2 &XFS_SB_VERSION2_LAZYSBCOUNTBIT ); +return (XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_5 ) || + (xfs_sb_version_hasmorebits (sbp) && + (sbp->sb_features2 &XFS_SB_VERSION2_LAZYSBCOUNTBIT )); }If we remove the version 5 check in
xfs_sb_hasmorebits(), then this change is correct. Otherwise, this change is not needed.No, this change means lazy superblock counters are a fixed feature of v5 superblocks - it is not optional like it currently is. The check inside
xfs_sb_version_hasmorebits()is to determine if the features2 field is present, not that the lazycount feature is supported....Quoted 11 lines
fs/xfs/xfs_sb.h static inline int xfs_sb_version_hasmorebits(xfs_sb_t *sbp) · line 528
Quoted 8 lines
fs/xfs/xfs_sb.h +3
-2static inline int xfs_sb_version_hasattr2 (xfs_sb_t *sbp) { -return xfs_sb_version_hasmorebits (sbp) && - (sbp->sb_features2 &XFS_SB_VERSION2_ATTR2BIT ); +return (XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_5 ) || + (xfs_sb_version_hasmorebits (sbp) && + (sbp->sb_features2 &XFS_SB_VERSION2_ATTR2BIT )); }If we remove the version 5 check in
xfs_sb_hasmorebits(), then this change is correct. Otherwise, this change is not needed.Same again - v5 implies attr2 behaviour is the only attr fork behaviour supported.
Quoted 13 lines
fs/xfs/xfs_sb.h static inline void xfs_sb_version_removeattr2(xfs_sb_t *sbp) · line 548
Quoted 11 lines
fs/xfs/xfs_sb.h +3
-2static inline void xfs_sb_version_addattr2 (xfs_sb_t *sbp)@@ -500,14 +542,14 @@ static inline void xfs_sb_version_removeattr2(xfs_sb_t *sbp)static inline int xfs_sb_version_hasprojid32bit (xfs_sb_t *sbp) { -return xfs_sb_version_hasmorebits (sbp) && - (sbp->sb_features2 &XFS_SB_VERSION2_PROJID32BIT ); +return (XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_5 ) || + (xfs_sb_version_hasmorebits (sbp) && + (sbp->sb_features2 &XFS_SB_VERSION2_PROJID32BIT )); }If we remove the version 5 check in
xfs_sb_hasmorebits(), then this change is correct. Otherwise, this change is not needed.Same again - v5 superblocks *always* support 32 bit project ids.
Quoted 8 lines
fs/xfs/xfs_sb.h static inline void xfs_sb_version_removeattr2(xfs_sb_t *sbp) · line 552
Quoted 5 lines
fs/xfs/xfs_sb.h +1
-2static inline int xfs_sb_version_hascrc (xfs_sb_t *sbp) { -return (xfs_sb_version_hasmorebits (sbp) && - (sbp->sb_features2 &XFS_SB_VERSION2_CRCBIT )); +return XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_5 ;what happens to the superblocks that already have version 4 and this bit set ?
It makes the
XFS_SB_VERSION2_CRCBITan invalid feature bit - it has never, ever been used by anything - so any filesystem with that bit set will fail to mount.Quoted 2 lines
Also don't
xfs_sb_version_toold()andxfs_sb_version_tonew()need changes ?No. the code that calls
xfs_sb_version_tonew()only does so for superblocks whose version is <= 3. i.e. filesystems that came from Irix 6.2 or earlier....Quoted 2 lines
I see that
xfs_sb_version_toold()is not used anywhere, can we remove it ?
Quoted 7 lines
Used by userspace, and seeing as this file is common between kernel and userspace, it hasn't been removed as that simply imposes higher maintenance cost on us.
Cheers,
Dave.
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 21/21] xfs: add CRC checks to the superblock
Quoted 61 lines · Chandra Seetharaman
Hi Dave,
Thanks for patiently explaining the details.
Please see my comments below.
Quoted 48 lines · Dave Chinner
Quoted 34 lines · Chandra Seetharaman
Quoted 31 lines · Dave Chinner
From: Dave Chinner <[email protected]>
With the addition of CRCs, there is such a wide and varied change to the on disk format that it makes sense to bump the superblock version number rather than try to use feature bits for all the new functionality.
This commit introduces all the new superblock fields needed for all the new functionality: feature masks similar to ext4, separate project quota inodes, a LSN field for recovery and the CRC field.
This commit does not bump the superblock version number, however. That will be done as a separate commit at the end of the series after all the new functionality is present so we switch it all on in one commit. This means that we can slowly introduce the changes without them being active and hence maintain bisectability of the tree.
This patch is based on a patch originally written by myself back from SGI days, which was subsequently modified by Christoph Hellwig. There is relatively little of that patch remaining, but the history of the patch still should be acknowledged here.
Signed-off-by Dave Chinner <[email protected]>--- fs/xfs/xfs_buf_item.h | 4 +- fs/xfs/xfs_log_recover.c | 8 ++++ fs/xfs/xfs_mount.c | 97 ++++++++++++++++++++++++++++++++++++-------- fs/xfs/xfs_mount.h | 1 + fs/xfs/xfs_sb.h | 100 ++++++++++++++++++++++++++++++++-------------- 5 files changed, 164 insertions(+), 46 deletions(-)<snip>
.....
Quoted 11 lines
fs/xfs/xfs_sb.h typedef enum { · line 310
Quoted 9 lines
fs/xfs/xfs_sb.h +5
-0@@ -276,6 +303,11 @@ typedef enum {#define XFS_SB_FDBLOCKS XFS_SB_MVAL(FDBLOCKS)#define XFS_SB_FEATURES2 XFS_SB_MVAL(FEATURES2)#define XFS_SB_BAD_FEATURES2 XFS_SB_MVAL(BAD_FEATURES2) +#define XFS_SB_FEATURES_COMPAT XFS_SB_MVAL(FEATURES_COMPAT) +#define XFS_SB_FEATURES_RO_COMPAT XFS_SB_MVAL(FEATURES_RO_COMPAT) +#define XFS_SB_FEATURES_INCOMPAT XFS_SB_MVAL(FEATURES_INCOMPAT) +#define XFS_SB_CRC XFS_SB_MVAL(CRC) +#define XFS_SB_PQUOTINO XFS_SB_MVAL(PQUOTINO)missing define for
XFS_SB_LSN?!Quoted 5 lines
No, not at all. We only have bits for variables that get logged. The LSn of the object is never logged as it is stamped into the object when it is being written back. i.e. it is an indication of when the object was last modified, not a field that is recorded during modifications.
Quoted 3 lines
Hmm. may be I misunderstood. Aren't these bits to inform the low level function (that selects which fields in superblocks are updated) which fields we want to update on the disk ?
They are bit fields fed to xfs_mod_sb() for transactional updates and to xfs_sb_to_disk() for copying specific fields from the in-core superblock to the on-disk superblock.
The LSN is written by neither of these methods - the LSN is pulled from the xfs_buf_log_item attached to the superblock buffer at writeback time and inserted directly into the buffer just prior to writeback. Hence it is not a field that should be visible to either xfs_mod_sb() or xfs_sb_to_disk().
Same goes for the CRC field.
Quoted 31 lines
Quoted 31 lines
Quoted 7 lines
Quoted 7 lines
fs/xfs/xfs_sb.h +2
-0@@ -325,6 +358,8 @@ static inline int xfs_sb_good_version(xfs_sb_t *sbp)return 1 ; } +if (XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_5 ) +return 1 ;Quoted 14 lines
fs/xfs/xfs_sb.h static inline int xfs_sb_version_hasattr(xfs_sb_t *sbp) · line 405
Quoted 10 lines
fs/xfs/xfs_sb.h +1
-1return 0 ; }@@ -365,7 +400,7 @@ static inline int xfs_sb_version_hasattr(xfs_sb_t *sbp) {return sbp->sb_versionnum ==XFS_SB_VERSION_2 || sbp->sb_versionnum ==XFS_SB_VERSION_3 || - (XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_4 && + (XFS_SB_VERSION_NUM (sbp) >=XFS_SB_VERSION_4 && (sbp->sb_versionnum &XFS_SB_VERSION_ATTRBIT )); }Do you expect version 5 and later have this bit to be exclusively set to use attribues ? (i.e can't we just assume version 5 and later would have attributes ?)
This just indicates that there are inodes with attributes in the filesystem. It's not an "enabling" feature at all. If it's not present when the first attribute is created, then the kernel code will set it. Hence all this does it maintain the existing behaviour....
Quoted 2 lines
Since we are changing the version, can't we get rid of some on these bits (i.e slowly deprecate them) ?
Quoted 8 lines
Quoted 2 lines
No, because we still support version 4 superblocks and hence all these bit for the indefinite future (i.e. forever).
Sorry. I used a wrong word "deprecate". That is not what I meant.
I wanted to see if by deliberately making few of the bits in versionnum/features2 implicit in version 5 can we start using the _same_ bits in version 5 for new features.
Insanity lies that way. A feature bit is for a single feature only. Forever. Version 5 superblocks add new feature fields for v5+ only features. The existing feature fields are needed for shared v4/v5 feature additions, and as they are shared, we cannot make them mean different things for different versions....
Cheers,
Dave.
Signature · 7 lines
Dave Chinner [email protected] _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
[PATCH 22/21] xfs: Fix magic number assert in xfs_dir3_leaf_log_bests
In reply to Dave ChinnerFrom: Dave Chinner <[email protected]>
Make sure we set the magic number correctly when converting from node to leaf form.
---
This should probably be folded into patch 14/21. I missed this hunk when bringing it forward to 3.9-rc2 and folding all the bugs fixes I had in debug patches back into their original patches.
fs/xfs/xfs_dir2_leaf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/xfs/xfs_dir2_leaf.c +1 -1
@@ -2199,7 +2199,7 @@ xfs_dir2_node_to_leaf(xfs_trans_buf_set_type (tp, lbp,XFS_BLF_DIR_LEAF1_BUF ); leafhdr.magic = (leafhdr.magic ==XFS_DIR2_LEAFN_MAGIC ) ?XFS_DIR2_LEAF1_MAGIC - :XFS_DIR3_LEAFN_MAGIC ; + :XFS_DIR3_LEAF1_MAGIC ;/* * Set up the leaf tail from the freespace block.
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
[PATCH 23/21] xfs: fix endian issues reported by sparse
In reply to Dave ChinnerFrom: Dave Chinner <[email protected]>
Sparse reports several problems in the new code with incorrect endian conversions being done on variables. Fix them.
--- fs/xfs/xfs_da_btree.c | 2 +- fs/xfs/xfs_dinode.h | 2 +- fs/xfs/xfs_dir2_block.c | 4 ++-- fs/xfs/xfs_dir2_data.c | 4 ++-- fs/xfs/xfs_dir2_leaf.c | 2 +- fs/xfs/xfs_dir2_node.c | 6 +++--- fs/xfs/xfs_mount.c | 1 - 7 files changed, 10 insertions(+), 11 deletions(-)
fs/xfs/xfs_da_btree.c +1 -1
@@ -2287,7 +2287,7 @@ xfs_da3_swap_lastblock( goto done; par_node = par_buf->b_addr;xfs_da3_node_hdr_from_disk (&par_hdr, par_node); -if (level >=0 && level !=be16_to_cpu (par_hdr.level) +1 ) { +if (level >=0 && level != par_hdr.level +1 ) {XFS_ERROR_REPORT ("xfs_da_swap_lastblock(4)" ,XFS_ERRLEVEL_LOW , mp); error =XFS_ERROR (EFSCORRUPTED );
fs/xfs/xfs_dinode.h +1 -1
@@ -72,7 +72,7 @@ typedef struct xfs_dinode {__be32 di_next_unlinked;/* agi unlinked list ptr */ /* start of the extended dinode, writable fields */ -__be32 di_crc;/* CRC of the inode */ +__le32 di_crc;/* CRC of the inode */ __be64 di_changecount;/* number of attribute changes */ __be64 di_lsn;/* flush sequence */ __be64 di_flags2;/* more random flags */
fs/xfs/xfs_dir2_block.c +2 -2
@@ -67,14 +67,14 @@ xfs_dir3_block_verify(struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;if (xfs_sb_version_hascrc (&mp->m_sb)) { -if (hdr3->magic !=be32_to_cpu (XFS_DIR3_BLOCK_MAGIC )) +if (hdr3->magic !=cpu_to_be32 (XFS_DIR3_BLOCK_MAGIC ))return false;if (!uuid_equal (&hdr3->uuid, &mp->m_sb.sb_uuid))return false;if (be64_to_cpu (hdr3->blkno) != bp->b_bn)return false; }else { -if (hdr3->magic !=be32_to_cpu (XFS_DIR2_BLOCK_MAGIC )) +if (hdr3->magic !=cpu_to_be32 (XFS_DIR2_BLOCK_MAGIC ))return false; }if (__xfs_dir3_data_check (NULL , bp))
fs/xfs/xfs_dir2_data.c +2 -2
@@ -200,14 +200,14 @@ xfs_dir3_data_verify(struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;if (xfs_sb_version_hascrc (&mp->m_sb)) { -if (hdr3->magic !=be32_to_cpu (XFS_DIR3_DATA_MAGIC )) +if (hdr3->magic !=cpu_to_be32 (XFS_DIR3_DATA_MAGIC ))return false;if (!uuid_equal (&hdr3->uuid, &mp->m_sb.sb_uuid))return false;if (be64_to_cpu (hdr3->blkno) != bp->b_bn)return false; }else { -if (hdr3->magic !=be32_to_cpu (XFS_DIR2_DATA_MAGIC )) +if (hdr3->magic !=cpu_to_be32 (XFS_DIR2_DATA_MAGIC ))return false; }if (__xfs_dir3_data_check (NULL , bp))
fs/xfs/xfs_dir2_leaf.c +1 -1
@@ -180,7 +180,7 @@ xfs_dir3_leaf1_check(static bool xfs_dir3_leaf_verify (struct xfs_buf *bp, -__be16 magic) +__uint16_t magic) {struct xfs_mount *mp = bp->b_target->bt_mount;struct xfs_dir2_leaf *leaf = bp->b_addr;
fs/xfs/xfs_dir2_node.c +3 -3
@@ -90,14 +90,14 @@ xfs_dir3_free_verify(if (xfs_sb_version_hascrc (&mp->m_sb)) {struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; -if (hdr3->magic !=be32_to_cpu (XFS_DIR3_FREE_MAGIC )) +if (hdr3->magic !=cpu_to_be32 (XFS_DIR3_FREE_MAGIC ))return false;if (!uuid_equal (&hdr3->uuid, &mp->m_sb.sb_uuid))return false;if (be64_to_cpu (hdr3->blkno) != bp->b_bn)return false; }else { -if (hdr->magic !=be32_to_cpu (XFS_DIR2_FREE_MAGIC )) +if (hdr->magic !=cpu_to_be32 (XFS_DIR2_FREE_MAGIC ))return false; }
@@ -1284,7 +1284,7 @@ xfs_dir2_leafn_remove( {struct xfs_dir3_icfree_hdr freehdr;xfs_dir3_free_hdr_from_disk (&freehdr, free); -ASSERT (be32_to_cpu (freehdr.firstdb) == +ASSERT (freehdr.firstdb ==xfs_dir3_free_max_bests (mp) * (fdb -XFS_DIR2_FREE_FIRSTDB (mp))); }
fs/xfs/xfs_mount.c +0 -1
@@ -568,7 +568,6 @@ xfs_sb_from_disk( to->sb_features_compat =be32_to_cpu (from->sb_features_compat); to->sb_features_ro_compat =be32_to_cpu (from->sb_features_ro_compat); to->sb_features_incompat =be32_to_cpu (from->sb_features_incompat); - to->sb_crc =be32_to_cpu (from->sb_crc); to->sb_pquotino =be64_to_cpu (from->sb_pquotino); to->sb_lsn =be64_to_cpu (from->sb_lsn); }
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
[PATCH 24/21] xfs: buffer type overruns blf_flags field
In reply to Dave ChinnerFrom: Dave Chinner <[email protected]>
The buffer type passed to log recvoery in the buffer log item overruns the blf_flags field. I had assumed that flags field was a 32 bit value, and it turns out it is a unsigned short. Therefore having 19 flags doesn't really work.
Convert the buffer type field to numeric value, and use the top 5 bits of the flags field for it. We currently have 17 types of buffers, so using 5 bits gives us plenty of room for expansion in future....
---
Found by sparse, indicating a value too large being placed into a 16 bit word.
fs/xfs/xfs_alloc.c | 4 +-- fs/xfs/xfs_attr_leaf.c | 6 ++-- fs/xfs/xfs_bmap.c | 2 +- fs/xfs/xfs_btree.c | 8 ++--- fs/xfs/xfs_buf_item.h | 90 +++++++++++++++++++++++++--------------------- fs/xfs/xfs_da_btree.c | 12 +++---- fs/xfs/xfs_dir2_block.c | 4 +-- fs/xfs/xfs_dir2_data.c | 4 +-- fs/xfs/xfs_dir2_leaf.c | 12 +++---- fs/xfs/xfs_dir2_node.c | 10 +++--- fs/xfs/xfs_ialloc.c | 2 +- fs/xfs/xfs_log_recover.c | 40 +++++++++++---------- fs/xfs/xfs_mount.c | 2 +- fs/xfs/xfs_trans_buf.c | 42 +++++++++++++++------- 14 files changed, 132 insertions(+), 106 deletions(-)
fs/xfs/xfs_alloc.c +2 -2
@@ -2099,7 +2099,7 @@ xfs_alloc_log_agf(trace_xfs_agf (tp->t_mountp,XFS_BUF_TO_AGF (bp), fields, _RET_IP_); -xfs_trans_buf_set_type (tp, bp,XFS_BLF_AGF_BUF ); +xfs_trans_buf_set_type (tp, bp,XFS_BLFT_AGF_BUF );xfs_btree_offsets (fields, offsets,XFS_AGF_NUM_BITS , &first, &last);xfs_trans_log_buf (tp, bp, (uint )first, (uint )last);
@@ -2179,7 +2179,7 @@ xfs_alloc_put_freelist(xfs_alloc_log_agf (tp, agbp, logflags); -xfs_trans_buf_set_type (tp, agflbp,XFS_BLF_AGFL_BUF ); +xfs_trans_buf_set_type (tp, agflbp,XFS_BLFT_AGFL_BUF );xfs_trans_log_buf (tp, agflbp, startoff, startoff +sizeof (xfs_agblock_t) -1 );return 0 ;
fs/xfs/xfs_attr_leaf.c +3 -3
@@ -276,7 +276,7 @@ xfs_attr3_leaf_read( err =xfs_da_read_buf (tp, dp, bno, mappedbno, bpp,XFS_ATTR_FORK , &xfs_attr3_leaf_buf_ops);if (!err && tp) -xfs_trans_buf_set_type (tp, *bpp,XFS_BLF_ATTR_LEAF_BUF ); +xfs_trans_buf_set_type (tp, *bpp,XFS_BLFT_ATTR_LEAF_BUF );return err; }
@@ -1083,7 +1083,7 @@ xfs_attr3_leaf_to_node( goto out;/* copy leaf to new buffer, update identifiers */ -xfs_trans_buf_set_type (args->trans, bp2,XFS_BLF_ATTR_LEAF_BUF ); +xfs_trans_buf_set_type (args->trans, bp2,XFS_BLFT_ATTR_LEAF_BUF ); bp2->b_ops = bp1->b_ops;memcpy (bp2->b_addr, bp1->b_addr,XFS_LBSIZE (mp));if (xfs_sb_version_hascrc (&mp->m_sb)) {
@@ -1146,7 +1146,7 @@ xfs_attr3_leaf_create(if (error)return error; bp->b_ops = &xfs_attr3_leaf_buf_ops; -xfs_trans_buf_set_type (args->trans, bp,XFS_BLF_ATTR_LEAF_BUF ); +xfs_trans_buf_set_type (args->trans, bp,XFS_BLFT_ATTR_LEAF_BUF ); leaf = bp->b_addr;memset (leaf,0 ,XFS_LBSIZE (mp));
fs/xfs/xfs_bmap.c +1 -1
@@ -1338,7 +1338,7 @@ xfs_bmap_local_to_extents_init_fn(ASSERT (0 ); bp->b_ops = &xfs_bmbt_buf_ops;memcpy (bp->b_addr, ifp->if_u1.if_data, ifp->if_bytes); -xfs_trans_buf_set_type (tp, bp,XFS_BLF_BTREE_BUF ); +xfs_trans_buf_set_type (tp, bp,XFS_BLFT_BTREE_BUF ); }/*
fs/xfs/xfs_btree.c +4 -4
@@ -1282,7 +1282,7 @@ xfs_btree_log_keys(XFS_BTREE_TRACE_ARGBII (cur, bp, first, last);if (bp) { -xfs_trans_buf_set_type (cur->bc_tp, bp,XFS_BLF_BTREE_BUF ); +xfs_trans_buf_set_type (cur->bc_tp, bp,XFS_BLFT_BTREE_BUF );xfs_trans_log_buf (cur->bc_tp, bp,xfs_btree_key_offset (cur, first),xfs_btree_key_offset (cur, last +1 ) -1 );
@@ -1307,7 +1307,7 @@ xfs_btree_log_recs(XFS_BTREE_TRACE_CURSOR (cur,XBT_ENTRY );XFS_BTREE_TRACE_ARGBII (cur, bp, first, last); -xfs_trans_buf_set_type (cur->bc_tp, bp,XFS_BLF_BTREE_BUF ); +xfs_trans_buf_set_type (cur->bc_tp, bp,XFS_BLFT_BTREE_BUF );xfs_trans_log_buf (cur->bc_tp, bp,xfs_btree_rec_offset (cur, first),xfs_btree_rec_offset (cur, last +1 ) -1 );
@@ -1332,7 +1332,7 @@ xfs_btree_log_ptrs(struct xfs_btree_block *block =XFS_BUF_TO_BLOCK (bp);int level =xfs_btree_get_level (block); -xfs_trans_buf_set_type (cur->bc_tp, bp,XFS_BLF_BTREE_BUF ); +xfs_trans_buf_set_type (cur->bc_tp, bp,XFS_BLFT_BTREE_BUF );xfs_trans_log_buf (cur->bc_tp, bp,xfs_btree_ptr_offset (cur, first, level),xfs_btree_ptr_offset (cur, last +1 , level) -1 );
@@ -1407,7 +1407,7 @@ xfs_btree_log_block( (cur->bc_flags &XFS_BTREE_LONG_PTRS ) ? loffsets : soffsets, nbits, &first, &last); -xfs_trans_buf_set_type (cur->bc_tp, bp,XFS_BLF_BTREE_BUF ); +xfs_trans_buf_set_type (cur->bc_tp, bp,XFS_BLFT_BTREE_BUF );xfs_trans_log_buf (cur->bc_tp, bp, first, last); }else { xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip,
fs/xfs/xfs_buf_item.h +49 -41
102 lines not on this page · raw message
fs/xfs/xfs_da_btree.c +6 -6
@@ -312,15 +312,15 @@ xfs_da3_node_read(switch (be16_to_cpu (info->magic)) {case XFS_DA3_NODE_MAGIC :case XFS_DA_NODE_MAGIC : - type =XFS_BLF_DA_NODE_BUF ; + type =XFS_BLFT_DA_NODE_BUF ;break ;case XFS_ATTR_LEAF_MAGIC :case XFS_ATTR3_LEAF_MAGIC : - type =XFS_BLF_ATTR_LEAF_BUF ; + type =XFS_BLFT_ATTR_LEAF_BUF ;break ;case XFS_DIR2_LEAFN_MAGIC :case XFS_DIR3_LEAFN_MAGIC : - type =XFS_BLF_DIR_LEAFN_BUF ; + type =XFS_BLFT_DIR_LEAFN_BUF ;break ;default : type =0 ;
@@ -361,7 +361,7 @@ xfs_da3_node_create(if (error)return (error); bp->b_ops = &xfs_da3_node_buf_ops; -xfs_trans_buf_set_type (tp, bp,XFS_BLF_DA_NODE_BUF ); +xfs_trans_buf_set_type (tp, bp,XFS_BLFT_DA_NODE_BUF ); node = bp->b_addr;if (xfs_sb_version_hascrc (&mp->m_sb)) {
@@ -595,7 +595,7 @@ xfs_da3_root_split(* we are about to copy oldroot to bp, so set up the type * of bp while we know exactly what it will be. */ -xfs_trans_buf_set_type (tp, bp,XFS_BLF_DA_NODE_BUF ); +xfs_trans_buf_set_type (tp, bp,XFS_BLFT_DA_NODE_BUF ); }else {struct xfs_dir3_icleaf_hdr leafhdr;struct xfs_dir2_leaf_entry *ents;
@@ -613,7 +613,7 @@ xfs_da3_root_split(* we are about to copy oldroot to bp, so set up the type * of bp while we know exactly what it will be. */ -xfs_trans_buf_set_type (tp, bp,XFS_BLF_DIR_LEAFN_BUF ); +xfs_trans_buf_set_type (tp, bp,XFS_BLFT_DIR_LEAFN_BUF ); }/*
fs/xfs/xfs_dir2_block.c +2 -2
@@ -137,7 +137,7 @@ xfs_dir3_block_read( err =xfs_da_read_buf (tp, dp, mp->m_dirdatablk,-1 , bpp,XFS_DATA_FORK , &xfs_dir3_block_buf_ops);if (!err && tp) -xfs_trans_buf_set_type (tp, *bpp,XFS_BLF_DIR_BLOCK_BUF ); +xfs_trans_buf_set_type (tp, *bpp,XFS_BLFT_DIR_BLOCK_BUF );return err; }
@@ -151,7 +151,7 @@ xfs_dir3_block_init(struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; bp->b_ops = &xfs_dir3_block_buf_ops; -xfs_trans_buf_set_type (tp, bp,XFS_BLF_DIR_BLOCK_BUF ); +xfs_trans_buf_set_type (tp, bp,XFS_BLFT_DIR_BLOCK_BUF );if (xfs_sb_version_hascrc (&mp->m_sb)) {memset (hdr3,0 ,sizeof (*hdr3));
fs/xfs/xfs_dir2_data.c +2 -2
@@ -306,7 +306,7 @@ xfs_dir3_data_read( err =xfs_da_read_buf (tp, dp, bno, mapped_bno, bpp,XFS_DATA_FORK , &xfs_dir3_data_buf_ops);if (!err && tp) -xfs_trans_buf_set_type (tp, *bpp,XFS_BLF_DIR_DATA_BUF ); +xfs_trans_buf_set_type (tp, *bpp,XFS_BLFT_DIR_DATA_BUF );return err; }
@@ -576,7 +576,7 @@ xfs_dir3_data_init(if (error)return error; bp->b_ops = &xfs_dir3_data_buf_ops; -xfs_trans_buf_set_type (tp, bp,XFS_BLF_DIR_DATA_BUF ); +xfs_trans_buf_set_type (tp, bp,XFS_BLFT_DIR_DATA_BUF );/* * Initialize the header.
fs/xfs/xfs_dir2_leaf.c +6 -6
@@ -300,7 +300,7 @@ xfs_dir3_leaf_read( err =xfs_da_read_buf (tp, dp, fbno, mappedbno, bpp,XFS_DATA_FORK , &xfs_dir3_leaf1_buf_ops);if (!err && tp) -xfs_trans_buf_set_type (tp, *bpp,XFS_BLF_DIR_LEAF1_BUF ); +xfs_trans_buf_set_type (tp, *bpp,XFS_BLFT_DIR_LEAF1_BUF );return err; }
@@ -317,7 +317,7 @@ xfs_dir3_leafn_read( err =xfs_da_read_buf (tp, dp, fbno, mappedbno, bpp,XFS_DATA_FORK , &xfs_dir3_leafn_buf_ops);if (!err && tp) -xfs_trans_buf_set_type (tp, *bpp,XFS_BLF_DIR_LEAFN_BUF ); +xfs_trans_buf_set_type (tp, *bpp,XFS_BLFT_DIR_LEAFN_BUF );return err; }
@@ -362,10 +362,10 @@ xfs_dir3_leaf_init( ltp =xfs_dir2_leaf_tail_p (mp, leaf); ltp->bestcount =0 ; bp->b_ops = &xfs_dir3_leaf1_buf_ops; -xfs_trans_buf_set_type (tp, bp,XFS_BLF_DIR_LEAF1_BUF ); +xfs_trans_buf_set_type (tp, bp,XFS_BLFT_DIR_LEAF1_BUF ); }else { bp->b_ops = &xfs_dir3_leafn_buf_ops; -xfs_trans_buf_set_type (tp, bp,XFS_BLF_DIR_LEAFN_BUF ); +xfs_trans_buf_set_type (tp, bp,XFS_BLFT_DIR_LEAFN_BUF ); } }
@@ -487,7 +487,7 @@ xfs_dir2_block_to_leaf(* Fix up the block header, make it a data block. */ dbp->b_ops = &xfs_dir3_data_buf_ops; -xfs_trans_buf_set_type (tp, dbp,XFS_BLF_DIR_DATA_BUF ); +xfs_trans_buf_set_type (tp, dbp,XFS_BLFT_DIR_DATA_BUF );if (hdr->magic ==cpu_to_be32 (XFS_DIR2_BLOCK_MAGIC )) hdr->magic =cpu_to_be32 (XFS_DIR2_DATA_MAGIC );else
@@ -2196,7 +2196,7 @@ xfs_dir2_node_to_leaf(xfs_dir3_leaf_compact (args, &leafhdr, lbp); lbp->b_ops = &xfs_dir3_leaf1_buf_ops; -xfs_trans_buf_set_type (tp, lbp,XFS_BLF_DIR_LEAF1_BUF ); +xfs_trans_buf_set_type (tp, lbp,XFS_BLFT_DIR_LEAF1_BUF ); leafhdr.magic = (leafhdr.magic ==XFS_DIR2_LEAFN_MAGIC ) ?XFS_DIR2_LEAF1_MAGIC :XFS_DIR3_LEAF1_MAGIC ;
fs/xfs/xfs_dir2_node.c +5 -5
@@ -165,7 +165,7 @@ __xfs_dir3_free_read(/* try read returns without an error or *bpp if it lands in a hole */ if (!err && tp && *bpp) -xfs_trans_buf_set_type (tp, *bpp,XFS_BLF_DIR_FREE_BUF ); +xfs_trans_buf_set_type (tp, *bpp,XFS_BLFT_DIR_FREE_BUF );return err; }
@@ -253,7 +253,7 @@ xfs_dir3_free_get_buf(if (error)return error; -xfs_trans_buf_set_type (tp, bp,XFS_BLF_DIR_FREE_BUF ); +xfs_trans_buf_set_type (tp, bp,XFS_BLFT_DIR_FREE_BUF ); bp->b_ops = &xfs_dir3_free_buf_ops;;/*
@@ -402,7 +402,7 @@ xfs_dir2_leaf_to_node(else leaf->hdr.info.magic =cpu_to_be16 (XFS_DIR3_LEAFN_MAGIC ); lbp->b_ops = &xfs_dir3_leafn_buf_ops; -xfs_trans_buf_set_type (tp, lbp,XFS_BLF_DIR_LEAFN_BUF ); +xfs_trans_buf_set_type (tp, lbp,XFS_BLFT_DIR_LEAFN_BUF );xfs_dir3_leaf_log_header (tp, lbp);xfs_dir3_leaf_check (mp, lbp);return 0 ;
@@ -814,7 +814,7 @@ xfs_dir2_leafn_lookup_for_entry( (char *)curbp->b_addr); state->extrablk.magic =XFS_DIR2_DATA_MAGIC ; curbp->b_ops = &xfs_dir3_data_buf_ops; -xfs_trans_buf_set_type (tp, curbp,XFS_BLF_DIR_DATA_BUF ); +xfs_trans_buf_set_type (tp, curbp,XFS_BLFT_DIR_DATA_BUF );if (cmp ==XFS_CMP_EXACT )return XFS_ERROR (EEXIST ); }
@@ -829,7 +829,7 @@ xfs_dir2_leafn_lookup_for_entry( state->extrablk.blkno = curdb; state->extrablk.magic =XFS_DIR2_DATA_MAGIC ; curbp->b_ops = &xfs_dir3_data_buf_ops; -xfs_trans_buf_set_type (tp, curbp,XFS_BLF_DIR_DATA_BUF ); +xfs_trans_buf_set_type (tp, curbp,XFS_BLFT_DIR_DATA_BUF ); }else {/* If the curbp is not the CI match block, drop it */ if (state->extrablk.bp != curbp)
fs/xfs/xfs_ialloc.c +1 -1
@@ -1474,7 +1474,7 @@ xfs_ialloc_log_agi(/* * Log the allocation group inode header buffer. */ -xfs_trans_buf_set_type (tp, bp,XFS_BLF_AGI_BUF ); +xfs_trans_buf_set_type (tp, bp,XFS_BLFT_AGI_BUF );xfs_trans_log_buf (tp, bp, first, last); }
fs/xfs/xfs_log_recover.c +21 -19
@@ -1888,8 +1888,8 @@ xlog_recovery_validate_buf_type( magic32 =be32_to_cpu (*(__be32 *)bp->b_addr); magic16 =be16_to_cpu (*(__be16 *)bp->b_addr); magicda =be16_to_cpu (info->magic); -switch (buf_f->blf_flags &XFS_BLF_TYPE_MASK ) { -case XFS_BLF_BTREE_BUF : +switch (xfs_blft_from_flags (buf_f)) { +case XFS_BLFT_BTREE_BUF :switch (magic32) {case XFS_ABTB_CRC_MAGIC :case XFS_ABTC_CRC_MAGIC :
@@ -1911,7 +1911,7 @@ xlog_recovery_validate_buf_type(break ; }break ; -case XFS_BLF_AGF_BUF : +case XFS_BLFT_AGF_BUF :if (magic32 !=XFS_AGF_MAGIC ) {xfs_warn (mp,"Bad AGF block magic!" );ASSERT (0 );
@@ -1919,7 +1919,7 @@ xlog_recovery_validate_buf_type( } bp->b_ops = &xfs_agf_buf_ops;break ; -case XFS_BLF_AGFL_BUF : +case XFS_BLFT_AGFL_BUF :if (!xfs_sb_version_hascrc (&mp->m_sb))break ;if (magic32 !=XFS_AGFL_MAGIC ) {
@@ -1929,7 +1929,7 @@ xlog_recovery_validate_buf_type( } bp->b_ops = &xfs_agfl_buf_ops;break ; -case XFS_BLF_AGI_BUF : +case XFS_BLFT_AGI_BUF :if (magic32 !=XFS_AGI_MAGIC ) {xfs_warn (mp,"Bad AGI block magic!" );ASSERT (0 );
@@ -1937,9 +1937,9 @@ xlog_recovery_validate_buf_type( } bp->b_ops = &xfs_agi_buf_ops;break ; -case XFS_BLF_UDQUOT_BUF : -case XFS_BLF_PDQUOT_BUF : -case XFS_BLF_GDQUOT_BUF : +case XFS_BLFT_UDQUOT_BUF : +case XFS_BLFT_PDQUOT_BUF : +case XFS_BLFT_GDQUOT_BUF :if (magic16 !=XFS_DQUOT_MAGIC ) {xfs_warn (mp,"Bad DQUOT block magic!" );ASSERT (0 );
@@ -1947,7 +1947,7 @@ xlog_recovery_validate_buf_type( } bp->b_ops = &xfs_dquot_buf_ops;break ; -case XFS_BLF_DINO_BUF : +case XFS_BLFT_DINO_BUF :/* * we get here with inode allocation buffers, not buffers that * track unlinked list changes.
@@ -1959,7 +1959,7 @@ xlog_recovery_validate_buf_type( } bp->b_ops = &xfs_inode_buf_ops;break ; -case XFS_BLF_SYMLINK_BUF : +case XFS_BLFT_SYMLINK_BUF :if (magic32 !=XFS_SYMLINK_MAGIC ) {xfs_warn (mp,"Bad symlink block magic!" );ASSERT (0 );
@@ -1967,7 +1967,7 @@ xlog_recovery_validate_buf_type( } bp->b_ops = &xfs_symlink_buf_ops;break ; -case XFS_BLF_DIR_BLOCK_BUF : +case XFS_BLFT_DIR_BLOCK_BUF :if (magic32 !=XFS_DIR2_BLOCK_MAGIC && magic32 !=XFS_DIR3_BLOCK_MAGIC ) {xfs_warn (mp,"Bad dir block magic!" );
@@ -1976,7 +1976,7 @@ xlog_recovery_validate_buf_type( } bp->b_ops = &xfs_dir3_block_buf_ops;break ; -case XFS_BLF_DIR_DATA_BUF : +case XFS_BLFT_DIR_DATA_BUF :if (magic32 !=XFS_DIR2_DATA_MAGIC && magic32 !=XFS_DIR3_DATA_MAGIC ) {xfs_warn (mp,"Bad dir data magic!" );
@@ -1985,7 +1985,7 @@ xlog_recovery_validate_buf_type( } bp->b_ops = &xfs_dir3_data_buf_ops;break ; -case XFS_BLF_DIR_FREE_BUF : +case XFS_BLFT_DIR_FREE_BUF :if (magic32 !=XFS_DIR2_FREE_MAGIC && magic32 !=XFS_DIR3_FREE_MAGIC ) {xfs_warn (mp,"Bad dir3 free magic!" );
@@ -1994,7 +1994,7 @@ xlog_recovery_validate_buf_type( } bp->b_ops = &xfs_dir3_free_buf_ops;break ; -case XFS_BLF_DIR_LEAF1_BUF : +case XFS_BLFT_DIR_LEAF1_BUF :if (magicda !=XFS_DIR2_LEAF1_MAGIC && magicda !=XFS_DIR3_LEAF1_MAGIC ) {xfs_warn (mp,"Bad dir leaf1 magic!" );
@@ -2003,7 +2003,7 @@ xlog_recovery_validate_buf_type( } bp->b_ops = &xfs_dir3_leaf1_buf_ops;break ; -case XFS_BLF_DIR_LEAFN_BUF : +case XFS_BLFT_DIR_LEAFN_BUF :if (magicda !=XFS_DIR2_LEAFN_MAGIC && magicda !=XFS_DIR3_LEAFN_MAGIC ) {xfs_warn (mp,"Bad dir leafn magic!" );
@@ -2012,7 +2012,7 @@ xlog_recovery_validate_buf_type( } bp->b_ops = &xfs_dir3_leafn_buf_ops;break ; -case XFS_BLF_DA_NODE_BUF : +case XFS_BLFT_DA_NODE_BUF :if (magicda !=XFS_DA_NODE_MAGIC && magicda !=XFS_DA3_NODE_MAGIC ) {xfs_warn (mp,"Bad da node magic!" );
@@ -2021,7 +2021,7 @@ xlog_recovery_validate_buf_type( } bp->b_ops = &xfs_da3_node_buf_ops;break ; -case XFS_BLF_ATTR_LEAF_BUF : +case XFS_BLFT_ATTR_LEAF_BUF :if (magicda !=XFS_ATTR_LEAF_MAGIC && magicda !=XFS_ATTR3_LEAF_MAGIC ) {xfs_warn (mp,"Bad attr leaf magic!" );
@@ -2030,7 +2030,7 @@ xlog_recovery_validate_buf_type( } bp->b_ops = &xfs_attr3_leaf_buf_ops;break ; -case XFS_BLF_ATTR_RMT_BUF : +case XFS_BLFT_ATTR_RMT_BUF :if (!xfs_sb_version_hascrc (&mp->m_sb))break ;if (magicda !=XFS_ATTR3_RMT_MAGIC ) {
@@ -2040,7 +2040,7 @@ xlog_recovery_validate_buf_type( } bp->b_ops = &xfs_attr3_rmt_buf_ops;break ; -case XFS_BLF_SB_BUF : +case XFS_BLFT_SB_BUF :if (magic32 !=XFS_SB_MAGIC ) {xfs_warn (mp,"Bad SB block magic!" );ASSERT (0 );
@@ -2049,6 +2049,8 @@ xlog_recovery_validate_buf_type( bp->b_ops = &xfs_sb_buf_ops;break ;default : +xfs_warn (mp,"Unknown buffer type %d!" , +xfs_blft_from_flags (buf_f));break ; } }
fs/xfs/xfs_mount.c +1 -1
@@ -1696,7 +1696,7 @@ xfs_mod_sb(xfs_trans_t *tp, __int64_t fields)ASSERT ((1LL << f) &XFS_SB_MOD_BITS ); first = xfs_sb_info[f].offset; -xfs_trans_buf_set_type (tp, bp,XFS_BLF_SB_BUF ); +xfs_trans_buf_set_type (tp, bp,XFS_BLFT_SB_BUF );xfs_trans_log_buf (tp, bp, first, last); }
fs/xfs/xfs_trans_buf.c +29 -13
101 lines not on this page · raw message
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Quoted 108 lines · Dave Chinner
Hi Folks,
Another week, another version. Previous versions:
http://oss.sgi.com/archives/xfs/2013-01/msg00328.html
http://oss.sgi.com/archives/xfs/2013-02/msg00451.htmlThis version is based on 3.9-rc2 + TOT xfsdev. I've just forward ported it from a 3.8.0 base where I've been working on it and testing for some time. Bugs that show up are likely to be a result of the forward porting, because I'm posting this before I've even run a full test cycle on 3.9-rc2. I'll probably send delta patches as followup bug fixes rather than reposting full patches, I think...
The first patch is an outstanding bug fix, the second is a change in corruption event output to make it output the entire headers of the corrupted buffer to make it easier to triage problems.
This new version contains:
- numerous bug fixes, mostly in the directory and attribute code.
- support for remote attributes
- directory/attribute buffer type tracking for log recovery
- some cleanup of rough corners in the dir/attr code.Still to do:
- DT_* type fields in the directory entries
- storage of attributes larger than 256 bytes in shortform attribute forks.
- extended superblock feature field checking (i.e. reject anything that is not zero)
- add mount warnings about CRC support being experimental
- Documentation (half written, not in series)In terms of testing, this patch set seems quite robust running on non-CRC enabled filesystems with existing tool chains. There are no regressions from xfstests, fsmark, dbench and other worklaods I've thrown at it, nor does there appear to be any significant performance impact from the modified code.
The CRC enabled code has been smoke tested. I haven't finished the userspace port so there is no repair/check functionality which means I cannot run xfstests on it yet. The attribute code is pretty much untested, but everything else seems to work fine. I can run it through my 50-million inode fsmark test (which creates, walks and removes 50 million inodes) without any problems occurring, so directory growing and shrinking is not obviously broken like it was last time.
To run with CRCs enabled, however, you need a mkfs.xfs patch to change the offsets of entries in short form directories. I'l post an updated patch set in the morning that at least enables this in userspace.
Comments, flames and questions welcome.
-Dave.
$ git diff --stat -C -M --summary 929724d.. fs/xfs/Makefile | 6 +- fs/xfs/xfs_ag.h | 56 +- fs/xfs/xfs_alloc.c | 199 ++++-- fs/xfs/xfs_alloc_btree.c | 105 ++- fs/xfs/xfs_alloc_btree.h | 12 +- fs/xfs/xfs_attr.c | 456 +++--------- fs/xfs/xfs_attr.h | 1 - fs/xfs/xfs_attr_leaf.c | 1780 +++++++++++++++++++++++++++-------------------- fs/xfs/xfs_attr_leaf.h | 122 +++- fs/xfs/xfs_attr_remote.c | 550 +++++++++++++++ fs/xfs/xfs_attr_remote.h | 46 ++ fs/xfs/xfs_bmap.c | 71 +- fs/xfs/xfs_bmap_btree.c | 110 ++- fs/xfs/xfs_bmap_btree.h | 19 +- fs/xfs/xfs_btree.c | 256 +++++-- fs/xfs/xfs_btree.h | 64 +- fs/xfs/xfs_buf.c | 6 + fs/xfs/xfs_buf_item.h | 52 +- fs/xfs/xfs_da_btree.c | 1500 ++++++++++++++++++++++++--------------- fs/xfs/xfs_da_btree.h | 130 +++- fs/xfs/xfs_dinode.h | 43 +- fs/xfs/xfs_dir2_block.c | 179 +++-- fs/xfs/xfs_dir2_data.c | 266 ++++--- fs/xfs/xfs_dir2_format.h | 290 +++++++- fs/xfs/xfs_dir2_leaf.c | 891 +++++++++++++++--------- fs/xfs/xfs_dir2_node.c | 992 ++++++++++++++++---------- fs/xfs/xfs_dir2_priv.h | 50 +- fs/xfs/xfs_dir2_sf.c | 12 +- fs/xfs/xfs_dquot.c | 112 ++- fs/xfs/xfs_error.c | 2 +- fs/xfs/xfs_file.c | 2 +- fs/xfs/xfs_fsops.c | 34 +- fs/xfs/xfs_ialloc.c | 80 ++- fs/xfs/xfs_ialloc_btree.c | 87 ++- fs/xfs/xfs_ialloc_btree.h | 9 +- fs/xfs/xfs_inode.c | 212 ++++-- fs/xfs/xfs_inode.h | 31 +- fs/xfs/xfs_inode_item.c | 2 +- fs/xfs/xfs_log_recover.c | 219 +++++- fs/xfs/xfs_mount.c | 97 ++- fs/xfs/xfs_mount.h | 1 + fs/xfs/xfs_qm.c | 23 +- fs/xfs/xfs_qm.h | 2 + fs/xfs/xfs_quota.h | 11 +- fs/xfs/xfs_sb.h | 100 ++- fs/xfs/xfs_symlink.c | 719 +++++++++++++++++++ fs/xfs/xfs_symlink.h | 53 ++ fs/xfs/xfs_trace.c | 2 +-
Quoted 8 lines
fs/xfs/xfs_trans.h | 4 + fs/xfs/xfs_trans_buf.c | 51 +- fs/xfs/xfs_vnodeops.c | 480 +------------ 51 files changed, 7034 insertions(+), 3563 deletions(-) create mode 100644 fs/xfs/xfs_attr_remote.c create mode 100644 fs/xfs/xfs_attr_remote.h create mode 100644 fs/xfs/xfs_symlink.c create mode 100644 fs/xfs/xfs_symlink.h
Applied #1 and #3.
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs