* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include <libxfs.h>
+#include "libxfs.h"
#include "avl.h"
#include "globals.h"
#include "agheader.h"
dinoc->di_magic = cpu_to_be16(XFS_DINODE_MAGIC);
}
- if (!XFS_DINODE_GOOD_VERSION(dinoc->di_version) ||
- (!fs_inode_nlink && dinoc->di_version > 1)) {
+ if (!xfs_dinode_good_version(mp, dinoc->di_version)) {
__dirty_no_modify_ret(dirty);
if (xfs_sb_version_hascrc(&mp->m_sb))
dinoc->di_version = 3;
else
- dinoc->di_version = (fs_inode_nlink) ? 2 : 1;
+ dinoc->di_version = 2;
}
if (be16_to_cpu(dinoc->di_mode) != 0) {
dinoc->di_ino = cpu_to_be64(ino_num);
}
- if (platform_uuid_compare(&dinoc->di_uuid, &mp->m_sb.sb_uuid)) {
+ if (platform_uuid_compare(&dinoc->di_uuid, &mp->m_sb.sb_meta_uuid)) {
__dirty_no_modify_ret(dirty);
- platform_uuid_copy(&dinoc->di_uuid, &mp->m_sb.sb_uuid);
+ platform_uuid_copy(&dinoc->di_uuid, &mp->m_sb.sb_meta_uuid);
}
for (i = 0; i < sizeof(dinoc->di_pad2)/sizeof(dinoc->di_pad2[0]); i++) {
xfs_agnumber_t agno,
xfs_agblock_t agbno)
{
- if (agno < (sbp->sb_agcount - 1))
+ if (agno < (sbp->sb_agcount - 1))
return (agbno >= sbp->sb_agblocks);
- if (agno == (sbp->sb_agcount - 1))
+ if (agno == (sbp->sb_agcount - 1))
return (agbno >= (sbp->sb_dblocks -
- ((xfs_drfsbno_t)(sbp->sb_agcount - 1) *
+ ((xfs_rfsblock_t)(sbp->sb_agcount - 1) *
sbp->sb_agblocks)));
return 1;
}
*/
int
verify_dfsbno(xfs_mount_t *mp,
- xfs_dfsbno_t fsbno)
+ xfs_fsblock_t fsbno)
{
xfs_agnumber_t agno;
xfs_agblock_t agbno;
static __inline int
verify_dfsbno_range(xfs_mount_t *mp,
- xfs_dfsbno_t fsbno,
- xfs_dfilblks_t count)
+ xfs_fsblock_t fsbno,
+ xfs_filblks_t count)
{
xfs_agnumber_t agno;
xfs_agblock_t agbno;
xfs_mount_t *mp,
xfs_bmbt_irec_t *irec,
xfs_ino_t ino,
- xfs_drfsbno_t *tot,
+ xfs_rfsblock_t *tot,
int check_dups)
{
- xfs_dfsbno_t b;
- xfs_drtbno_t ext;
+ xfs_fsblock_t b;
+ xfs_rtblock_t ext;
int state;
int pwe; /* partially-written extent */
*/
for (b = irec->br_startblock; b < irec->br_startblock +
irec->br_blockcount; b += mp->m_sb.sb_rextsize) {
- ext = (xfs_drtbno_t) b / mp->m_sb.sb_rextsize;
+ ext = (xfs_rtblock_t) b / mp->m_sb.sb_rextsize;
pwe = xfs_sb_version_hasextflgbit(&mp->m_sb) &&
irec->br_state == XFS_EXT_UNWRITTEN &&
(b % mp->m_sb.sb_rextsize != 0);
int *numrecs,
int type,
xfs_ino_t ino,
- xfs_drfsbno_t *tot,
+ xfs_rfsblock_t *tot,
blkmap_t **blkmapp,
- xfs_dfiloff_t *first_key,
- xfs_dfiloff_t *last_key,
+ xfs_fileoff_t *first_key,
+ xfs_fileoff_t *last_key,
int check_dups,
int whichfork)
{
xfs_bmbt_irec_t irec;
- xfs_dfilblks_t cp = 0; /* prev count */
- xfs_dfsbno_t sp = 0; /* prev start */
- xfs_dfiloff_t op = 0; /* prev offset */
- xfs_dfsbno_t b;
+ xfs_filblks_t cp = 0; /* prev count */
+ xfs_fsblock_t sp = 0; /* prev start */
+ xfs_fileoff_t op = 0; /* prev offset */
+ xfs_fsblock_t b;
char *ftype;
char *forkname = get_forkname(whichfork);
int i;
ftype = ftype_regular;
for (i = 0; i < *numrecs; i++) {
- libxfs_bmbt_disk_get_all(rp + i, &irec);
+ libxfs_bmbt_disk_get_all((rp +i), &irec);
if (i == 0)
*last_key = *first_key = irec.br_startoff;
else
irec.br_startoff);
goto done;
}
- if (irec.br_startoff >= fs_max_file_offset) {
+ /* Ensure this extent does not extend beyond the max offset */
+ if (irec.br_startoff + irec.br_blockcount - 1 >
+ fs_max_file_offset) {
do_warn(
-_("inode %" PRIu64 " - extent offset too large - start %" PRIu64 ", "
- "count %" PRIu64 ", offset %" PRIu64 "\n"),
- ino, irec.br_startblock, irec.br_blockcount,
- irec.br_startoff);
+_("inode %" PRIu64 " - extent exceeds max offset - start %" PRIu64 ", "
+ "count %" PRIu64 ", physical block %" PRIu64 "\n"),
+ ino, irec.br_startoff, irec.br_blockcount,
+ irec.br_startblock);
goto done;
}
int *numrecs,
int type,
xfs_ino_t ino,
- xfs_drfsbno_t *tot,
+ xfs_rfsblock_t *tot,
blkmap_t **blkmapp,
- xfs_dfiloff_t *first_key,
- xfs_dfiloff_t *last_key,
+ xfs_fileoff_t *first_key,
+ xfs_fileoff_t *last_key,
int whichfork)
{
return process_bmbt_reclist_int(mp, rp, numrecs, type, ino, tot,
int *numrecs,
int type,
xfs_ino_t ino,
- xfs_drfsbno_t *tot,
+ xfs_rfsblock_t *tot,
int whichfork)
{
- xfs_dfiloff_t first_key = 0;
- xfs_dfiloff_t last_key = 0;
+ xfs_fileoff_t first_key = 0;
+ xfs_fileoff_t last_key = 0;
return process_bmbt_reclist_int(mp, rp, numrecs, type, ino, tot,
NULL, &first_key, &last_key, 1, whichfork);
xfs_dinode_t *dip,
int type,
int *dirty,
- xfs_drfsbno_t *tot,
+ xfs_rfsblock_t *tot,
__uint64_t *nex,
blkmap_t **blkmapp,
int whichfork,
int check_dups)
{
xfs_bmdr_block_t *dib;
- xfs_dfiloff_t last_key;
- xfs_dfiloff_t first_key = 0;
+ xfs_fileoff_t last_key;
+ xfs_fileoff_t first_key = 0;
xfs_ino_t lino;
xfs_bmbt_ptr_t *pp;
xfs_bmbt_key_t *pkey;
init_bm_cursor(&cursor, level + 1);
pp = XFS_BMDR_PTR_ADDR(dib, 1,
- xfs_bmdr_maxrecs(mp, XFS_DFORK_SIZE(dip, mp, whichfork), 0));
+ xfs_bmdr_maxrecs(XFS_DFORK_SIZE(dip, mp, whichfork), 0));
pkey = XFS_BMDR_KEY_ADDR(dib, 1);
- last_key = NULLDFILOFF;
+ last_key = NULLFILEOFF;
for (i = 0; i < numrecs; i++) {
/*
* btree, we'd do it right here. For now, if there's a
* problem, we'll bail out and presumably clear the inode.
*/
- if (!verify_dfsbno(mp, be64_to_cpu(pp[i]))) {
- do_warn(_("bad bmap btree ptr 0x%llx in ino %" PRIu64 "\n"),
- (unsigned long long) be64_to_cpu(pp[i]), lino);
+ if (!verify_dfsbno(mp, get_unaligned_be64(&pp[i]))) {
+ do_warn(
+_("bad bmap btree ptr 0x%" PRIx64 " in ino %" PRIu64 "\n"),
+ get_unaligned_be64(&pp[i]), lino);
return(1);
}
- if (scan_lbtree(be64_to_cpu(pp[i]), level, scan_bmapbt, type,
- whichfork, lino, tot, nex, blkmapp, &cursor,
- 1, check_dups, magic, &xfs_bmbt_buf_ops))
+ if (scan_lbtree(get_unaligned_be64(&pp[i]), level, scan_bmapbt,
+ type, whichfork, lino, tot, nex, blkmapp,
+ &cursor, 1, check_dups, magic,
+ &xfs_bmbt_buf_ops))
return(1);
/*
* fix key (offset) mismatches between the keys in root
* blocks but the parent hasn't been updated
*/
if (!check_dups && cursor.level[level-1].first_key !=
- be64_to_cpu(pkey[i].br_startoff)) {
+ get_unaligned_be64(&pkey[i].br_startoff)) {
if (!no_modify) {
do_warn(
- _("correcting key in bmbt root (was %llu, now %" PRIu64") in inode "
- "%" PRIu64" %s fork\n"),
- (unsigned long long)
- be64_to_cpu(pkey[i].br_startoff),
- cursor.level[level-1].first_key,
- XFS_AGINO_TO_INO(mp, agno, ino),
- forkname);
+_("correcting key in bmbt root (was %" PRIu64 ", now %" PRIu64") in inode "
+ "%" PRIu64" %s fork\n"),
+ get_unaligned_be64(&pkey[i].br_startoff),
+ cursor.level[level-1].first_key,
+ XFS_AGINO_TO_INO(mp, agno, ino),
+ forkname);
*dirty = 1;
- pkey[i].br_startoff = cpu_to_be64(
- cursor.level[level-1].first_key);
+ put_unaligned_be64(
+ cursor.level[level-1].first_key,
+ &pkey[i].br_startoff);
} else {
do_warn(
- _("bad key in bmbt root (is %llu, would reset to %" PRIu64 ") in inode "
- "%" PRIu64 " %s fork\n"),
- (unsigned long long)
- be64_to_cpu(pkey[i].br_startoff),
- cursor.level[level-1].first_key,
- XFS_AGINO_TO_INO(mp, agno, ino),
- forkname);
+_("bad key in bmbt root (is %" PRIu64 ", would reset to %" PRIu64 ") in inode "
+ "%" PRIu64 " %s fork\n"),
+ get_unaligned_be64(&pkey[i].br_startoff),
+ cursor.level[level-1].first_key,
+ XFS_AGINO_TO_INO(mp, agno, ino),
+ forkname);
}
}
/*
* inode if the ordering doesn't hold
*/
if (check_dups == 0) {
- if (last_key != NULLDFILOFF && last_key >=
+ if (last_key != NULLFILEOFF && last_key >=
cursor.level[level-1].first_key) {
do_warn(
_("out of order bmbt root key %" PRIu64 " in inode %" PRIu64 " %s fork\n"),
* is NULL.
*/
if (check_dups == 0 &&
- cursor.level[0].right_fsbno != NULLDFSBNO) {
+ cursor.level[0].right_fsbno != NULLFSBLOCK) {
do_warn(
- _("bad fwd (right) sibling pointer (saw %" PRIu64 " should be NULLDFSBNO)\n"),
+ _("bad fwd (right) sibling pointer (saw %" PRIu64 " should be NULLFSBLOCK)\n"),
cursor.level[0].right_fsbno);
do_warn(
_("\tin inode %" PRIu64 " (%s fork) bmap btree block %" PRIu64 "\n"),
xfs_dinode_t *dip,
int type,
int *dirty,
- xfs_drfsbno_t *tot,
+ xfs_rfsblock_t *tot,
__uint64_t *nex,
blkmap_t **blkmapp,
int whichfork,
{
xfs_ino_t lino;
xfs_bmbt_rec_t *rp;
- xfs_dfiloff_t first_key;
- xfs_dfiloff_t last_key;
+ xfs_fileoff_t first_key;
+ xfs_fileoff_t last_key;
int32_t numrecs;
int ret;
static int
process_symlink_extlist(xfs_mount_t *mp, xfs_ino_t lino, xfs_dinode_t *dino)
{
- xfs_dfiloff_t expected_offset;
+ xfs_fileoff_t expected_offset;
xfs_bmbt_rec_t *rp;
xfs_bmbt_irec_t irec;
int numrecs;
int max_blocks;
if (be64_to_cpu(dino->di_size) <= XFS_DFORK_DSIZE(dino, mp)) {
- if (dino->di_format == XFS_DINODE_FMT_LOCAL)
+ if (dino->di_format == XFS_DINODE_FMT_LOCAL)
return 0;
do_warn(
_("mismatch between format (%d) and size (%" PRId64 ") in symlink ino %" PRIu64 "\n"),
expected_offset = 0;
for (i = 0; i < numrecs; i++) {
- libxfs_bmbt_disk_get_all(rp + i, &irec);
-
+ libxfs_bmbt_disk_get_all((rp +i), &irec);
if (irec.br_startoff != expected_offset) {
do_warn(
_("bad extent #%d offset (%" PRIu64 ") in symlink %" PRIu64 " data fork\n"),
struct blkmap *blkmap,
char *dst)
{
- xfs_dfsbno_t fsbno;
+ xfs_fsblock_t fsbno;
struct xfs_buf *bp;
char *src;
int pathlen;
int badcrc = 0;
fsbno = blkmap_get(blkmap, i);
- if (fsbno == NULLDFSBNO) {
+ if (fsbno == NULLFSBLOCK) {
do_warn(
_("cannot read inode %" PRIu64 ", file block %d, NULL disk block\n"),
lino, i);
lino, i, fsbno);
return 1;
}
- if (bp->b_error == EFSBADCRC) {
+ if (bp->b_error == -EFSBADCRC) {
do_warn(
_("Bad symlink buffer CRC, block %" PRIu64 ", inode %" PRIu64 ".\n"
"Correcting CRC, but symlink may be bad.\n"), fsbno, lino);
src = bp->b_addr;
if (xfs_sb_version_hascrc(&mp->m_sb)) {
- if (!libxfs_symlink_hdr_ok(mp, lino, offset,
- byte_cnt, bp)) {
+ if (!libxfs_symlink_hdr_ok(lino, offset,
+ byte_cnt, bp)) {
do_warn(
_("bad symlink header ino %" PRIu64 ", file block %d, disk block %" PRIu64 "\n"),
lino, i, fsbno);
xfs_dinode_t *dino,
blkmap_t *blkmap)
{
- char *symlink, *cptr;
+ char *symlink;
char data[MAXPATHLEN];
/*
* local symlink, just copy the symlink out of the
* inode into the data area
*/
- memmove(symlink, XFS_DFORK_DPTR(dino),
+ memmove(symlink, XFS_DFORK_DPTR(dino),
be64_to_cpu(dino->di_size));
} else {
int error;
return(1);
}
- /*
- * check for any component being too long
- */
- if (be64_to_cpu(dino->di_size) >= MAXNAMELEN) {
- cptr = strchr(symlink, '/');
-
- while (cptr != NULL) {
- if (cptr - symlink >= MAXNAMELEN) {
- do_warn(
-_("component of symlink in inode %" PRIu64 " too long\n"),
- lino);
- return(1);
- }
- symlink = cptr + 1;
- cptr = strchr(symlink, '/');
- }
-
- if (strlen(symlink) >= MAXNAMELEN) {
- do_warn(
-_("component of symlink in inode %" PRIu64 " too long\n"),
- lino);
- return(1);
- }
- }
-
return(0);
}
}
static int
-process_misc_ino_types_blocks(xfs_drfsbno_t totblocks, xfs_ino_t lino, int type)
+process_misc_ino_types_blocks(xfs_rfsblock_t totblocks, xfs_ino_t lino, int type)
{
/*
* you can not enforce all misc types have zero data fork blocks
static int
process_inode_blocks_and_extents(
xfs_dinode_t *dino,
- xfs_drfsbno_t nblocks,
+ xfs_rfsblock_t nblocks,
__uint64_t nextents,
__uint64_t anextents,
xfs_ino_t lino,
xfs_dinode_t *dino,
int type,
int *dirty,
- xfs_drfsbno_t *totblocks,
+ xfs_rfsblock_t *totblocks,
__uint64_t *nextents,
blkmap_t **dblkmap,
int check_dups)
*/
switch (dino->di_format) {
case XFS_DINODE_FMT_LOCAL:
- err = process_lclinode(mp, agno, ino, dino,
+ err = process_lclinode(mp, agno, ino, dino,
XFS_DATA_FORK);
break;
case XFS_DINODE_FMT_EXTENTS:
xfs_dinode_t *dino,
int type,
int *dirty,
- xfs_drfsbno_t *atotblocks,
+ xfs_rfsblock_t *atotblocks,
__uint64_t *anextents,
int check_dups,
int extra_attr_check,
if (check_dups) {
switch (dino->di_aformat) {
case XFS_DINODE_FMT_LOCAL:
- err = process_lclinode(mp, agno, ino, dino,
+ err = process_lclinode(mp, agno, ino, dino,
XFS_ATTR_FORK);
break;
case XFS_DINODE_FMT_EXTENTS:
{
int dirty = 0;
- if (dino->di_version > 1 && !fs_inode_nlink) {
- /*
- * do we have a fs/inode version mismatch with a valid
- * version 2 inode here that has to stay version 2 or
- * lose links?
- */
- if (be32_to_cpu(dino->di_nlink) > XFS_MAXLINK_1) {
- /*
- * yes. are nlink inodes allowed?
- */
- if (fs_inode_nlink_allowed) {
- /*
- * yes, update status variable which will
- * cause sb to be updated later.
- */
- fs_inode_nlink = 1;
- do_warn
- (_("version 2 inode %" PRIu64 " claims > %u links, "),
- lino, XFS_MAXLINK_1);
- if (!no_modify) {
- do_warn(
- _("updating superblock version number\n"));
- } else {
- do_warn(
- _("would update superblock version number\n"));
- }
- } else {
- /*
- * no, have to convert back to onlinks
- * even if we lose some links
- */
- do_warn(
- _("WARNING: version 2 inode %" PRIu64 " claims > %u links, "),
- lino, XFS_MAXLINK_1);
- if (!no_modify) {
- do_warn(_("converting back to version 1,\n"
- "this may destroy %d links\n"),
- be32_to_cpu(dino->di_nlink) -
- XFS_MAXLINK_1);
-
- dino->di_version = 1;
- dino->di_nlink = cpu_to_be32(XFS_MAXLINK_1);
- dino->di_onlink = cpu_to_be16(XFS_MAXLINK_1);
- dirty = 1;
- } else {
- do_warn(_("would convert back to version 1,\n"
- "\tthis might destroy %d links\n"),
- be32_to_cpu(dino->di_nlink) -
- XFS_MAXLINK_1);
- }
- }
- } else {
- /*
- * do we have a v2 inode that we could convert back
- * to v1 without losing any links? if we do and
- * we have a mismatch between superblock bits and the
- * version bit, alter the version bit in this case.
- *
- * the case where we lost links was handled above.
- */
- do_warn(_("found version 2 inode %" PRIu64 ", "), lino);
- if (!no_modify) {
- do_warn(_("converting back to version 1\n"));
- dino->di_version = 1;
- dino->di_onlink = cpu_to_be16(
- be32_to_cpu(dino->di_nlink));
- dirty = 1;
- } else {
- do_warn(_("would convert back to version 1\n"));
- }
- }
- }
-
/*
- * ok, if it's still a version 2 inode, it's going
- * to stay a version 2 inode. it should have a zero
+ * if it's a version 2 inode, it should have a zero
* onlink field, so clear it.
*/
- if (dino->di_version > 1 &&
- dino->di_onlink != 0 && fs_inode_nlink > 0) {
+ if (dino->di_version > 1 && dino->di_onlink != 0) {
if (!no_modify) {
do_warn(
_("clearing obsolete nlink field in version 2 inode %" PRIu64 ", was %d, now 0\n"),
int *isa_dir, /* out == 1 if inode is a directory */
xfs_ino_t *parent) /* out -- parent if ino is a dir */
{
- xfs_drfsbno_t totblocks = 0;
- xfs_drfsbno_t atotblocks = 0;
+ xfs_rfsblock_t totblocks = 0;
+ xfs_rfsblock_t atotblocks = 0;
int di_mode;
int type;
int retval = 0;
*/
ASSERT(uncertain == 0 || verify_mode != 0);
+ /*
+ * This is the only valid point to check the CRC; after this we may have
+ * made changes which invalidate it, and the CRC is only updated again
+ * when it gets written out.
+ *
+ * Of course if we make any modifications after this, the inode gets
+ * rewritten, and the CRC is updated automagically.
+ */
+ if (xfs_sb_version_hascrc(&mp->m_sb) &&
+ !xfs_verify_cksum((char *)dino, mp->m_sb.sb_inodesize,
+ XFS_DINODE_CRC_OFF)) {
+ retval = 1;
+ if (!uncertain)
+ do_warn(_("bad CRC for inode %" PRIu64 "%c"),
+ lino, verify_mode ? '\n' : ',');
+ if (!verify_mode) {
+ if (!no_modify) {
+ do_warn(_(" will rewrite\n"));
+ *dirty = 1;
+ } else
+ do_warn(_(" would rewrite\n"));
+ }
+ }
+
if (be16_to_cpu(dino->di_magic) != XFS_DINODE_MAGIC) {
retval = 1;
if (!uncertain)
}
}
- if (!XFS_DINODE_GOOD_VERSION(dino->di_version) ||
- (!fs_inode_nlink && dino->di_version > 1) ||
- (xfs_sb_version_hascrc(&mp->m_sb) && dino->di_version < 3) ) {
+ if (!xfs_dinode_good_version(mp, dino->di_version)) {
retval = 1;
if (!uncertain)
do_warn(_("bad version number 0x%x on inode %" PRIu64 "%c"),
if (!no_modify) {
do_warn(_(" resetting version number\n"));
dino->di_version =
- xfs_sb_version_hascrc(&mp->m_sb) ? 3 :
- (fs_inode_nlink) ? 2 : 1;
+ xfs_sb_version_hascrc(&mp->m_sb) ? 3 : 2;
*dirty = 1;
} else
do_warn(_(" would reset version number\n"));
return 1;
goto clear_bad_out;
}
- if (platform_uuid_compare(&dino->di_uuid, &mp->m_sb.sb_uuid)) {
+ if (platform_uuid_compare(&dino->di_uuid,
+ &mp->m_sb.sb_meta_uuid)) {
if (!uncertain)
do_warn(
_("UUID mismatch on inode %" PRIu64 "\n"), lino);